https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ee7f479c57623dffcf92507380a16d7b0a51dbb5
commit ee7f479c57623dffcf92507380a16d7b0a51dbb5 Author: Mark Jansen <mark.jan...@reactos.org> AuthorDate: Mon Feb 19 22:23:39 2018 +0100 Commit: Mark Jansen <mark.jan...@reactos.org> CommitDate: Mon Feb 19 22:23:39 2018 +0100 [RTL][XDK][KERNERL32_WINETEST] Import wine actctx changes from 3.2-37c98396 This adds support for reading the trustInfo (requestedExecutionLevel), and the compatibility (supportedOs) sections. --- dll/win32/kernel32/client/actctx.c | 2 + modules/rostests/winetests/kernel32/actctx.c | 303 +++++++++++++++++++++--- sdk/include/xdk/winnt_old.h | 16 ++ sdk/lib/rtl/actctx.c | 337 +++++++++++++++++++++++++-- 4 files changed, 610 insertions(+), 48 deletions(-) diff --git a/dll/win32/kernel32/client/actctx.c b/dll/win32/kernel32/client/actctx.c index f268e2731a..302d6c86a3 100644 --- a/dll/win32/kernel32/client/actctx.c +++ b/dll/win32/kernel32/client/actctx.c @@ -374,6 +374,8 @@ QueryActCtxW(IN DWORD dwFlags, { case ActivationContextBasicInformation: case ActivationContextDetailedInformation: + case CompatibilityInformationInActivationContext: + case RunlevelInformationInActivationContext: /* Nothing to check */ break; diff --git a/modules/rostests/winetests/kernel32/actctx.c b/modules/rostests/winetests/kernel32/actctx.c index 5a41c40218..8bd37c43f3 100644 --- a/modules/rostests/winetests/kernel32/actctx.c +++ b/modules/rostests/winetests/kernel32/actctx.c @@ -395,6 +395,57 @@ static const char wrong_depmanifest1[] = "<assemblyIdentity type=\"win32\" name=\"testdep\" version=\"6.5.4.4\" processorArchitecture=\"" ARCH "\" />" "</assembly>"; +static const char compat_manifest_no_supportedOs[] = +"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" +" <assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>" +" <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">" +" <application>" +" </application>" +" </compatibility>" +"</assembly>"; + +static const char compat_manifest_vista[] = +"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" +" <assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>" +" <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">" +" <application>" +" <supportedOS Id=\"{e2011457-1546-43c5-a5fe-008deee3d3f0}\" />" /* Windows Vista */ +" </application>" +" </compatibility>" +"</assembly>"; + +static const char compat_manifest_vista_7_8_10_81[] = +"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" +" <assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>" +" <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">" +" <application>" +" <supportedOS Id=\"{e2011457-1546-43c5-a5fe-008deee3d3f0}\" />" /* Windows Vista */ +" <supportedOS Id=\"{35138b9a-5d96-4fbd-8e2d-a2440225f93a}\" />" /* Windows 7 */ +" <supportedOS Id=\"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}\" />" /* Windows 8 */ +" <supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\" />" /* Windows 10 */ +" <supportedOS Id=\"{1f676c76-80e1-4239-95bb-83d0f6d0da78}\" />" /* Windows 8.1 */ +" </application>" +" </compatibility>" +"</assembly>"; + +static const char compat_manifest_other_guid[] = +"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" +" <assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>" +" <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">" +" <application>" +" <supportedOS Id=\"{12345566-1111-2222-3333-444444444444}\" />" +" </application>" +" </compatibility>" +"</assembly>"; + +DEFINE_GUID(VISTA_COMPAT_GUID, 0xe2011457, 0x1546, 0x43c5, 0xa5, 0xfe, 0x00, 0x8d, 0xee, 0xe3, 0xd3, 0xf0); +DEFINE_GUID(WIN7_COMPAT_GUID, 0x35138b9a, 0x5d96, 0x4fbd, 0x8e, 0x2d, 0xa2, 0x44, 0x02, 0x25, 0xf9, 0x3a); +DEFINE_GUID(WIN8_COMPAT_GUID, 0x4a2f28e3, 0x53b9, 0x4441, 0xba, 0x9c, 0xd6, 0x9d, 0x4a, 0x4a, 0x6e, 0x38); +DEFINE_GUID(WIN81_COMPAT_GUID, 0x1f676c76, 0x80e1, 0x4239, 0x95, 0xbb, 0x83, 0xd0, 0xf6, 0xd0, 0xda, 0x78); +DEFINE_GUID(WIN10_COMPAT_GUID, 0x8e0f7a12, 0xbfb3, 0x4fe8, 0xb9, 0xa5, 0x48, 0xfd, 0x50, 0xa1, 0x5a, 0x9a); +DEFINE_GUID(OTHER_COMPAT_GUID, 0x12345566, 0x1111, 0x2222, 0x33, 0x33, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44); + + static const WCHAR testlib_dll[] = {'t','e','s','t','l','i','b','.','d','l','l',0}; static const WCHAR testlib2_dll[] = @@ -894,7 +945,7 @@ static HANDLE test_create(const char *file) return handle; } -static void test_create_and_fail(const char *manifest, const char *depmanifest, int todo) +static void test_create_and_fail(const char *manifest, const char *depmanifest, int todo, BOOL is_broken) { ACTCTXW actctx; HANDLE handle; @@ -909,8 +960,14 @@ static void test_create_and_fail(const char *manifest, const char *depmanifest, handle = pCreateActCtxW(&actctx); todo_wine_if(todo) { - ok(handle == INVALID_HANDLE_VALUE, "handle != INVALID_HANDLE_VALUE\n"); - ok(GetLastError() == ERROR_SXS_CANT_GEN_ACTCTX, "GetLastError == %u\n", GetLastError()); + if (is_broken) + ok(broken(handle != INVALID_HANDLE_VALUE) || handle == INVALID_HANDLE_VALUE, + "Unexpected context handle %p.\n", handle); + else + ok(handle == INVALID_HANDLE_VALUE, "Unexpected context handle %p.\n", handle); + + if (handle == INVALID_HANDLE_VALUE) + ok(GetLastError() == ERROR_SXS_CANT_GEN_ACTCTX, "Unexpected error %d.\n", GetLastError()); } if (handle != INVALID_HANDLE_VALUE) pReleaseActCtx( handle ); DeleteFileA("bad.manifest"); @@ -953,31 +1010,31 @@ static void test_create_fail(void) ok(GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError == %u\n", GetLastError()); trace("wrong_manifest1\n"); - test_create_and_fail(wrong_manifest1, NULL, 0 ); + test_create_and_fail(wrong_manifest1, NULL, 0, FALSE); trace("wrong_manifest2\n"); - test_create_and_fail(wrong_manifest2, NULL, 0 ); + test_create_and_fail(wrong_manifest2, NULL, 0, FALSE); trace("wrong_manifest3\n"); - test_create_and_fail(wrong_manifest3, NULL, 1 ); + test_create_and_fail(wrong_manifest3, NULL, 1, FALSE); trace("wrong_manifest4\n"); - test_create_and_fail(wrong_manifest4, NULL, 1 ); + test_create_and_fail(wrong_manifest4, NULL, 1, FALSE); trace("wrong_manifest5\n"); - test_create_and_fail(wrong_manifest5, NULL, 0 ); + test_create_and_fail(wrong_manifest5, NULL, 0, FALSE); trace("wrong_manifest6\n"); - test_create_and_fail(wrong_manifest6, NULL, 0 ); + test_create_and_fail(wrong_manifest6, NULL, 0, FALSE); trace("wrong_manifest7\n"); - test_create_and_fail(wrong_manifest7, NULL, 1 ); + test_create_and_fail(wrong_manifest7, NULL, 1, FALSE); trace("wrong_manifest8\n"); - test_create_and_fail(wrong_manifest8, NULL, 0 ); + test_create_and_fail(wrong_manifest8, NULL, 0, FALSE); trace("wrong_manifest9\n"); - test_create_and_fail(wrong_manifest9, NULL, 0 ); + test_create_and_fail(wrong_manifest9, NULL, 0, TRUE /* WinXP */); trace("wrong_manifest10\n"); - test_create_and_fail(wrong_manifest10, NULL, 0 ); + test_create_and_fail(wrong_manifest10, NULL, 0, TRUE /* WinXP */); trace("UTF-16 manifest1 without BOM\n"); test_create_wide_and_fail(manifest1, FALSE ); trace("manifest2\n"); - test_create_and_fail(manifest2, NULL, 0 ); + test_create_and_fail(manifest2, NULL, 0, FALSE); trace("manifest2+depmanifest1\n"); - test_create_and_fail(manifest2, wrong_depmanifest1, 0 ); + test_create_and_fail(manifest2, wrong_depmanifest1, 0, FALSE); } struct strsection_header @@ -1909,8 +1966,6 @@ static void test_actctx(void) HANDLE handle; BOOL b; - test_create_fail(); - trace("default actctx\n"); b = pGetCurrentActCtx(&handle); @@ -2095,7 +2150,8 @@ static void test_actctx(void) if(create_manifest_file("test6.manifest", manifest6, -1, NULL, NULL)) { handle = test_create("test6.manifest"); - ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError()); + ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* WinXP */, + "Unexpected context handle %p.\n", handle); DeleteFileA("test6.manifest"); DeleteFileA("testdep.manifest"); if(handle != INVALID_HANDLE_VALUE) @@ -2267,7 +2323,7 @@ static HANDLE create_manifest(const char *filename, const char *data, int line) return handle; } -static void kernel32_find(ULONG section, const char *string_to_find, BOOL should_find, int line) +static void kernel32_find(ULONG section, const char *string_to_find, BOOL should_find, BOOL todo, int line) { UNICODE_STRING string_to_findW; ACTCTX_SECTION_KEYED_DATA data; @@ -2284,6 +2340,7 @@ static void kernel32_find(ULONG section, const char *string_to_find, BOOL should err = GetLastError(); ok_(__FILE__, line)(ret == should_find, "FindActCtxSectionStringA: expected ret = %u, got %u\n", should_find, ret); + todo_wine_if(todo) ok_(__FILE__, line)(err == (should_find ? ERROR_SUCCESS : ERROR_SXS_KEY_NOT_FOUND), "FindActCtxSectionStringA: unexpected error %u\n", err); @@ -2295,6 +2352,7 @@ static void kernel32_find(ULONG section, const char *string_to_find, BOOL should err = GetLastError(); ok_(__FILE__, line)(ret == should_find, "FindActCtxSectionStringW: expected ret = %u, got %u\n", should_find, ret); + todo_wine_if(todo) ok_(__FILE__, line)(err == (should_find ? ERROR_SUCCESS : ERROR_SXS_KEY_NOT_FOUND), "FindActCtxSectionStringW: unexpected error %u\n", err); @@ -2317,7 +2375,7 @@ static void kernel32_find(ULONG section, const char *string_to_find, BOOL should pRtlFreeUnicodeString(&string_to_findW); } -static void ntdll_find(ULONG section, const char *string_to_find, BOOL should_find, int line) +static void ntdll_find(ULONG section, const char *string_to_find, BOOL should_find, BOOL todo, int line) { UNICODE_STRING string_to_findW; ACTCTX_SECTION_KEYED_DATA data; @@ -2329,10 +2387,12 @@ static void ntdll_find(ULONG section, const char *string_to_find, BOOL should_fi data.cbSize = sizeof(data); ret = pRtlFindActivationContextSectionString(0, NULL, section, &string_to_findW, &data); + todo_wine_if(todo) ok_(__FILE__, line)(ret == (should_find ? STATUS_SUCCESS : STATUS_SXS_KEY_NOT_FOUND), "RtlFindActivationContextSectionString: unexpected status 0x%x\n", ret); ret = pRtlFindActivationContextSectionString(0, NULL, section, &string_to_findW, NULL); + todo_wine_if(todo) ok_(__FILE__, line)(ret == (should_find ? STATUS_SUCCESS : STATUS_SXS_KEY_NOT_FOUND), "RtlFindActivationContextSectionString: unexpected status 0x%x\n", ret); @@ -2350,22 +2410,22 @@ static void test_findsectionstring(void) ok(ret, "ActivateActCtx failed: %u\n", GetLastError()); /* first we show the parameter validation from kernel32 */ - kernel32_find(ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION, "testdep", FALSE, __LINE__); - kernel32_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib.dll", TRUE, __LINE__); - kernel32_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib2.dll", TRUE, __LINE__); - kernel32_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib3.dll", FALSE, __LINE__); - kernel32_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass", TRUE, __LINE__); - kernel32_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass2", TRUE, __LINE__); - kernel32_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass3", FALSE, __LINE__); + kernel32_find(ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION, "testdep", FALSE, TRUE, __LINE__); + kernel32_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib.dll", TRUE, FALSE, __LINE__); + kernel32_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib2.dll", TRUE, FALSE, __LINE__); + kernel32_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib3.dll", FALSE, FALSE, __LINE__); + kernel32_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass", TRUE, FALSE, __LINE__); + kernel32_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass2", TRUE, FALSE, __LINE__); + kernel32_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass3", FALSE, FALSE, __LINE__); /* then we show that ntdll plays by different rules */ - ntdll_find(ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION, "testdep", FALSE, __LINE__); - ntdll_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib.dll", TRUE, __LINE__); - ntdll_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib2.dll", TRUE, __LINE__); - ntdll_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib3.dll", FALSE, __LINE__); - ntdll_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass", TRUE, __LINE__); - ntdll_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass2", TRUE, __LINE__); - ntdll_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass3", FALSE, __LINE__); + ntdll_find(ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION, "testdep", FALSE, TRUE, __LINE__); + ntdll_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib.dll", TRUE, FALSE, __LINE__); + ntdll_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib2.dll", TRUE, FALSE, __LINE__); + ntdll_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib3.dll", FALSE, FALSE, __LINE__); + ntdll_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass", TRUE, FALSE, __LINE__); + ntdll_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass2", TRUE, FALSE, __LINE__); + ntdll_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass3", FALSE, FALSE, __LINE__); ret = pDeactivateActCtx(0, cookie); ok(ret, "DeactivateActCtx failed: %u\n", GetLastError()); @@ -2683,6 +2743,179 @@ todo_wine pReleaseActCtx(handle); } +/* Test structure to verify alignment */ +typedef struct _test_act_ctx_compat_info { + DWORD ElementCount; + COMPATIBILITY_CONTEXT_ELEMENT Elements[10]; +} test_act_ctx_compat_info; + +static void test_no_compat(HANDLE handle, int line) +{ + test_act_ctx_compat_info compat_info; + SIZE_T size; + BOOL b; + + memset(&compat_info, 0, sizeof(compat_info)); + b = pQueryActCtxW(QUERY_ACTCTX_FLAG_NO_ADDREF, handle, NULL, + CompatibilityInformationInActivationContext, &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)(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) +{ + 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; + + memset(&compat_info, 0, sizeof(compat_info)); + b = pQueryActCtxW(QUERY_ACTCTX_FLAG_NO_ADDREF, handle, NULL, + CompatibilityInformationInActivationContext, &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)(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 == ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS, + "Wrong type, got %u for %u\n", (DWORD)compat_info.Elements[n].Type, n); + } +} + +static void test_compatibility(void) +{ + HANDLE handle; + + /* No compat results returned */ + trace("manifest1\n"); + if(!create_manifest_file("test1.manifest", manifest1, -1, NULL, NULL)) + { + skip("Could not create manifest file\n"); + return; + } + handle = test_create("test1.manifest"); + ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError()); + DeleteFileA("test1.manifest"); + if(handle != INVALID_HANDLE_VALUE) + { + char buffer[sizeof(COMPATIBILITY_CONTEXT_ELEMENT) * 2 + sizeof(DWORD)]; + SIZE_T size; + BOOL b; + + memset(buffer, 0, sizeof(buffer)); + b = pQueryActCtxW(QUERY_ACTCTX_FLAG_NO_ADDREF, handle, NULL, + CompatibilityInformationInActivationContext, buffer, + sizeof(buffer), &size); + + if (!b && GetLastError() == ERROR_INVALID_PARAMETER) + { + win_skip("CompatibilityInformationInActivationContext not supported.\n"); + pReleaseActCtx(handle); + return; + } + + test_basic_info(handle, __LINE__); + test_no_compat(handle, __LINE__); + pReleaseActCtx(handle); + } + + /* Still no compat results returned */ + trace("no_supportedOs\n"); + if(!create_manifest_file("no_supportedOs.manifest", compat_manifest_no_supportedOs, -1, NULL, NULL)) + { + skip("Could not create manifest file\n"); + return; + } + handle = test_create("no_supportedOs.manifest"); + ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError()); + DeleteFileA("no_supportedOs.manifest"); + if(handle != INVALID_HANDLE_VALUE) + { + test_basic_info(handle, __LINE__); + test_no_compat(handle, __LINE__); + pReleaseActCtx(handle); + } + + /* Just one result returned */ + trace("manifest_vista\n"); + if(!create_manifest_file("manifest_vista.manifest", compat_manifest_vista, -1, NULL, NULL)) + { + skip("Could not create manifest file\n"); + return; + } + handle = test_create("manifest_vista.manifest"); + ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError()); + DeleteFileA("manifest_vista.manifest"); + if(handle != INVALID_HANDLE_VALUE) + { + static const GUID* expect_manifest[] = + { + &VISTA_COMPAT_GUID + }; + test_basic_info(handle, __LINE__); + test_with_compat(handle, 1, expect_manifest, __LINE__); + pReleaseActCtx(handle); + } + + /* Show that the order is retained */ + trace("manifest_vista_7_8_10_81\n"); + if(!create_manifest_file("manifest_vista_7_8_10_81.manifest", compat_manifest_vista_7_8_10_81, -1, NULL, NULL)) + { + skip("Could not create manifest file\n"); + return; + } + handle = test_create("manifest_vista_7_8_10_81.manifest"); + ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError()); + DeleteFileA("manifest_vista_7_8_10_81.manifest"); + if(handle != INVALID_HANDLE_VALUE) + { + static const GUID* expect_manifest[] = + { + &VISTA_COMPAT_GUID, + &WIN7_COMPAT_GUID, + &WIN8_COMPAT_GUID, + &WIN10_COMPAT_GUID, + &WIN81_COMPAT_GUID, + }; + test_basic_info(handle, __LINE__); + test_with_compat(handle, 5, expect_manifest, __LINE__); + pReleaseActCtx(handle); + } + + /* Show that even unknown GUID's are stored */ + trace("manifest_other_guid\n"); + if(!create_manifest_file("manifest_other_guid.manifest", compat_manifest_other_guid, -1, NULL, NULL)) + { + skip("Could not create manifest file\n"); + return; + } + handle = test_create("manifest_other_guid.manifest"); + ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError()); + DeleteFileA("manifest_other_guid.manifest"); + if(handle != INVALID_HANDLE_VALUE) + { + static const GUID* expect_manifest[] = + { + &OTHER_COMPAT_GUID, + }; + test_basic_info(handle, __LINE__); + test_with_compat(handle, 1, expect_manifest, __LINE__); + pReleaseActCtx(handle); + } +} + START_TEST(actctx) { int argc; @@ -2703,8 +2936,10 @@ START_TEST(actctx) } test_actctx(); + test_create_fail(); test_CreateActCtx(); test_findsectionstring(); test_ZombifyActCtx(); run_child_process(); + test_compatibility(); } diff --git a/sdk/include/xdk/winnt_old.h b/sdk/include/xdk/winnt_old.h index 415f332a82..f03582ab88 100644 --- a/sdk/include/xdk/winnt_old.h +++ b/sdk/include/xdk/winnt_old.h @@ -3908,6 +3908,22 @@ typedef struct _ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION { DWORD UiAccess; } ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION, *PACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION; +typedef enum { + ACTCX_COMPATIBILITY_ELEMENT_TYPE_UNKNOWN = 0, + ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS +} ACTCTX_COMPATIBILITY_ELEMENT_TYPE; + +typedef struct _COMPATIBILITY_CONTEXT_ELEMENT { + GUID Id; + ACTCTX_COMPATIBILITY_ELEMENT_TYPE Type; +} COMPATIBILITY_CONTEXT_ELEMENT, *PCOMPATIBILITY_CONTEXT_ELEMENT; + +typedef struct _ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION { + DWORD ElementCount; + COMPATIBILITY_CONTEXT_ELEMENT Elements[]; +} ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION, *PACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION; + + #define ACTIVATION_CONTEXT_PATH_TYPE_NONE 1 #define ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE 2 #define ACTIVATION_CONTEXT_PATH_TYPE_URL 3 diff --git a/sdk/lib/rtl/actctx.c b/sdk/lib/rtl/actctx.c index 396b442fcd..545f5fe1a1 100644 --- a/sdk/lib/rtl/actctx.c +++ b/sdk/lib/rtl/actctx.c @@ -12,7 +12,7 @@ * Samuel Serapi�n */ -/* Based on Wine Staging 1.7.37 */ +/* Based on Wine 3.2-37c98396 */ #include <rtl.h> #include <ntstrsafe.h> @@ -441,15 +441,19 @@ enum assembly_type struct assembly { - enum assembly_type type; - struct assembly_identity id; - struct file_info manifest; - WCHAR *directory; - BOOL no_inherit; - struct dll_redirect *dlls; - unsigned int num_dlls; - unsigned int allocated_dlls; - struct entity_array entities; + enum assembly_type type; + struct assembly_identity id; + struct file_info manifest; + WCHAR *directory; + BOOL no_inherit; + struct dll_redirect *dlls; + unsigned int num_dlls; + unsigned int allocated_dlls; + struct entity_array entities; + COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts; + ULONG num_compat_contexts; + ACTCTX_REQUESTED_RUN_LEVEL run_level; + ULONG ui_access; }; enum context_sections @@ -652,6 +656,16 @@ 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}; +static const WCHAR requestedExecutionLevelW[] = {'r','e','q','u','e','s','t','e','d','E','x','e','c','u','t','i','o','n','L','e','v','e','l',0}; +static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0}; +static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0}; +static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0}; + struct olemisc_entry { const WCHAR *name; @@ -827,6 +841,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( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, + assembly->compat_contexts, + new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) ); + } + else + { + ptr = RtlAllocateHeap( RtlGetProcessHeap(), 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( RtlGetProcessHeap(), 0, ai->name ); @@ -1118,6 +1151,7 @@ static void actctx_release( ACTIVATION_CONTEXT *actctx ) RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls ); RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info ); RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory ); + RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->compat_contexts ); free_entity_array( &assembly->entities ); free_assembly_identity(&assembly->id); } @@ -2319,6 +2353,229 @@ 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 + { + UNICODE_STRING attr_valueU = xmlstr2unicode(&attr_value); + DPRINT1("Invalid guid %wZ\n", &attr_valueU); + } + } + else + { + UNICODE_STRING attr_nameU = xmlstr2unicode(&attr_name); + UNICODE_STRING attr_valueU = xmlstr2unicode(&attr_value); + DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); + } + } + } + else + { + UNICODE_STRING elemU = xmlstr2unicode(&elem); + DPRINT1("unknown elem %wZ\n", &elemU); + 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 + { + UNICODE_STRING elemU = xmlstr2unicode(&elem); + DPRINT1("unknown elem %wZ\n", &elemU); + ret = parse_unknown_elem(xmlbuf, &elem); + } + } + return ret; +} + +static BOOL parse_requested_execution_level_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl) +{ + static const WCHAR levelW[] = {'l','e','v','e','l',0}; + static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0}; + static const WCHAR requireAdministratorW[] = {'r','e','q','u','i','r','e','A','d','m','i','n','i','s','t','r','a','t','o','r',0}; + static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0}; + static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0}; + static const WCHAR falseW[] = {'f','a','l','s','e',0}; + static const WCHAR trueW[] = {'t','r','u','e',0}; + + xmlstr_t attr_name, attr_value, elem; + BOOL end = FALSE, ret = TRUE, error; + + /* Multiple requestedExecutionLevel elements are not supported. */ + if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) + return FALSE; + + while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) + { + UNICODE_STRING attr_nameU = xmlstr2unicode(&attr_name); + UNICODE_STRING attr_valueU = xmlstr2unicode(&attr_value); + if (xmlstr_cmp(&attr_name, levelW)) + { + if (xmlstr_cmpi(&attr_value, asInvokerW)) + assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER; + else if (xmlstr_cmpi(&attr_value, highestAvailableW)) + assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE; + else if (xmlstr_cmpi(&attr_value, requireAdministratorW)) + assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN; + else + DPRINT1("unknown execution level: %wZ\n", &attr_valueU); + } + else if (xmlstr_cmp(&attr_name, uiAccessW)) + { + if (xmlstr_cmpi(&attr_value, falseW)) + assembly->ui_access = FALSE; + else if (xmlstr_cmpi(&attr_value, trueW)) + assembly->ui_access = TRUE; + else + DPRINT1("unknown uiAccess value: %wZ\n", &attr_valueU); + } + else + DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); + } + + if (error) return FALSE; + if (end) return TRUE; + + while (ret && (ret = next_xml_elem(xmlbuf, &elem))) + { + if (xmlstr_cmp_end(&elem, requestedExecutionLevelW)) + { + ret = parse_end_element(xmlbuf); + break; + } + else + { + UNICODE_STRING elemU = xmlstr2unicode(&elem); + DPRINT1("unknown element %wZ\n", &elemU); + ret = parse_unknown_elem(xmlbuf, &elem); + } + } + + return ret; +} + +static BOOL parse_requested_privileges_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, requestedPrivilegesW)) + { + ret = parse_end_element(xmlbuf); + break; + } + else if (xmlstr_cmp(&elem, requestedExecutionLevelW)) + ret = parse_requested_execution_level_elem(xmlbuf, assembly, acl); + else + { + UNICODE_STRING elemU = xmlstr2unicode(&elem); + DPRINT1("unknown elem %wZ\n", &elemU); + ret = parse_unknown_elem(xmlbuf, &elem); + } + } + + return ret; +} + +static BOOL parse_security_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, securityW)) + { + ret = parse_end_element(xmlbuf); + break; + } + else if (xmlstr_cmp(&elem, requestedPrivilegesW)) + ret = parse_requested_privileges_elem(xmlbuf, assembly, acl); + else + { + UNICODE_STRING elemU = xmlstr2unicode(&elem); + DPRINT1("unknown elem %wZ\n", &elemU); + ret = parse_unknown_elem(xmlbuf, &elem); + } + } + + return ret; +} + +static BOOL parse_trust_info_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, trustInfoW)) + { + ret = parse_end_element(xmlbuf); + break; + } + else if (xmlstr_cmp(&elem, securityW)) + ret = parse_security_elem(xmlbuf, assembly, acl); + else + { + UNICODE_STRING elemU = xmlstr2unicode(&elem); + DPRINT1("unknown elem %wZ\n", &elemU); + 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) @@ -2411,6 +2668,11 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, { ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl); } + else if (xml_elem_cmp(&elem, trustInfoW, asmv2W) || + xml_elem_cmp(&elem, trustInfoW, asmv1W)) + { + ret = parse_trust_info_elem(xmlbuf, assembly, acl); + } else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W)) { if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE; @@ -2440,12 +2702,10 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, } } } -#ifdef __REACTOS__ - else if (xml_elem_cmp(&elem, L"trustInfo", asmv1W)) + else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW)) { - ret = parse_unknown_elem(xmlbuf, &elem); + ret = parse_compatibility_elem(xmlbuf, assembly, acl); } -#endif else { attr_nameU = xmlstr2unicode(&elem); @@ -5273,6 +5533,55 @@ NTSTATUS NTAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, } break; + case CompatibilityInformationInActivationContext: + { + /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer; + COMPATIBILITY_CONTEXT_ELEMENT *elements; + 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(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT); + + if (retlen) *retlen = len; + if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; + + *acci = num_compat_contexts; + elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1); + for (n = 0; n < num_compat_contexts; ++n) + { + elements[n] = assembly->compat_contexts[n]; + } + } + break; + + case RunlevelInformationInActivationContext: + { + ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer; + struct assembly *assembly; + SIZE_T len; + + if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; + + len = sizeof(*acrli); + if (retlen) *retlen = len; + if (!buffer || bufsize < len) + return STATUS_BUFFER_TOO_SMALL; + + assembly = actctx->assemblies; + + acrli->ulFlags = 0; + acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED; + acrli->UiAccess = assembly ? assembly->ui_access : 0; + } + break; + default: DPRINT( "class %u not implemented\n", class ); return STATUS_NOT_IMPLEMENTED;