Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/kernel32/tests/Makefile.in | 5 +
dlls/kernel32/tests/resource.rc | 12 +
dlls/kernel32/tests/sxs.c | 313 +++++++++++++++++++++++++
dlls/kernel32/tests/sxs_dll_1.c | 17 ++
dlls/kernel32/tests/sxs_dll_1.manifest | 7 +
dlls/kernel32/tests/sxs_dll_1.spec | 1 +
dlls/kernel32/tests/sxs_dll_2.c | 17 ++
dlls/kernel32/tests/sxs_dll_2.manifest | 7 +
dlls/kernel32/tests/sxs_dll_2.spec | 1 +
dlls/kernel32/tests/sxs_exe_1.manifest | 8 +
dlls/kernel32/tests/sxs_exe_2.manifest | 8 +
11 files changed, 396 insertions(+)
create mode 100644 dlls/kernel32/tests/sxs.c
create mode 100644 dlls/kernel32/tests/sxs_dll_1.c
create mode 100644 dlls/kernel32/tests/sxs_dll_1.manifest
create mode 100644 dlls/kernel32/tests/sxs_dll_1.spec
create mode 100644 dlls/kernel32/tests/sxs_dll_2.c
create mode 100644 dlls/kernel32/tests/sxs_dll_2.manifest
create mode 100644 dlls/kernel32/tests/sxs_dll_2.spec
create mode 100644 dlls/kernel32/tests/sxs_exe_1.manifest
create mode 100644 dlls/kernel32/tests/sxs_exe_2.manifest
diff --git a/dlls/kernel32/tests/Makefile.in b/dlls/kernel32/tests/Makefile.in
index e06141d9f6..0318cae322 100644
--- a/dlls/kernel32/tests/Makefile.in
+++ b/dlls/kernel32/tests/Makefile.in
@@ -29,6 +29,11 @@ SOURCES = \
profile.c \
resource.c \
resource.rc \
+ sxs.c \
+ sxs_dll_1.c \
+ sxs_dll_1.spec \
+ sxs_dll_2.c \
+ sxs_dll_2.spec \
sync.c \
thread.c \
time.c \
diff --git a/dlls/kernel32/tests/resource.rc b/dlls/kernel32/tests/resource.rc
index f40a87819e..1512a477aa 100644
--- a/dlls/kernel32/tests/resource.rc
+++ b/dlls/kernel32/tests/resource.rc
@@ -24,3 +24,15 @@
{
MENUITEM "foo", 1
}
+
+/* @makedep: sxs_exe_1.manifest */
+sxs_exe_1.manifest RCDATA sxs_exe_1.manifest
+
+/* @makedep: sxs_exe_2.manifest */
+sxs_exe_2.manifest RCDATA sxs_exe_2.manifest
+
+/* @makedep: sxs_dll_1.manifest */
+sxs_dll_1.manifest RCDATA sxs_dll_1.manifest
+
+/* @makedep: sxs_dll_2.manifest */
+sxs_dll_2.manifest RCDATA sxs_dll_2.manifest
diff --git a/dlls/kernel32/tests/sxs.c b/dlls/kernel32/tests/sxs.c
new file mode 100644
index 0000000000..ed3bb06514
--- /dev/null
+++ b/dlls/kernel32/tests/sxs.c
@@ -0,0 +1,313 @@
+/*
+ * Side by side tests
+ *
+ * Copyright 2019 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/test.h"
+#include <winbase.h>
+#include <windef.h>
+#include "winuser.h"
+#include <stdio.h>
+
+static BOOL write_resource_file(const char *path_tmp, const char *name_res, const char *name_file, char *path_file)
+{
+ HRSRC rsrc;
+ void *rsrc_data;
+ DWORD rsrc_size;
+ BOOL ret;
+ HANDLE hfile;
+
+ rsrc = FindResourceA(GetModuleHandleA(NULL), name_res, (LPCSTR)RT_RCDATA);
+ if (!rsrc)
+ {
+ rsrc = FindResourceA(GetModuleHandleA(NULL), name_res, (LPCSTR)"TESTDLL");
+ if (!rsrc) return FALSE;
+ }
+
+ rsrc_data = LockResource(LoadResource(GetModuleHandleA(NULL), rsrc));
+ if (!rsrc_data) return FALSE;
+
+ rsrc_size = SizeofResource(GetModuleHandleA(NULL), rsrc);
+ if (!rsrc_size) return FALSE;
+
+ sprintf(path_file, "%s%s", path_tmp, name_file);
+ hfile = CreateFileA(path_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (hfile == INVALID_HANDLE_VALUE) return FALSE;
+
+ ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
+
+ CloseHandle(hfile);
+ return ret;
+}
+
+static void get_application_directory(char *buffer, int buffer_size)
+{
+ char *end;
+ GetModuleFileNameA(NULL, buffer, buffer_size);
+ end = strrchr(buffer, '\\');
+ end[1] = 0;
+}
+
+typedef struct
+{
+ char path_tmp[MAX_PATH];
+ char path_dll[MAX_PATH];
+ char path_manifest_exe[MAX_PATH];
+ char path_manifest_dll[MAX_PATH];
+ ACTCTXA context;
+ ULONG_PTR cookie;
+ HANDLE handle_context;
+ HMODULE module;
+ DWORD(WINAPI *test_func)(void);
+} sxs_info;
+
+static int fill_sxs_info(sxs_info *info, const char *temp, const char *path_dll, const char *exe_manifest, const char *dll_manifest)
+{
+ BOOL success;
+
+ GetTempPathA(MAX_PATH, info->path_tmp);
+ strcat(info->path_tmp, temp);
+ strcat(info->path_tmp, "\\");
+ CreateDirectoryA(info->path_tmp, NULL);
+
+ if (!write_resource_file(info->path_tmp, path_dll, "sxs_dll.dll", info->path_dll))
+ {
+ skip("Failed to create file for testing\n");
+ return 1;
+ }
+
+ if (!write_resource_file(info->path_tmp, exe_manifest, exe_manifest, info->path_manifest_exe))
+ {
+ skip("Failed to create file for testing\n");
+ return 1;
+ }
+
+ if (!write_resource_file(info->path_tmp, dll_manifest, "sxs_dll.manifest", info->path_manifest_dll))
+ {
+ skip("Failed to create file for testing\n");
+ return 1;
+ }
+
+ info->context.cbSize = sizeof(ACTCTXA);
+ info->context.lpSource = info->path_manifest_exe;
+ info->context.lpAssemblyDirectory = info->path_tmp;
+ info->context.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
+
+ info->handle_context = CreateActCtxA(&info->context);
+ ok((info->handle_context != NULL && info->handle_context != INVALID_HANDLE_VALUE )|| broken(GetLastError() == 14001),
+ "CreateActCtxA failed: %d\n", GetLastError());
+ if (GetLastError() == 14001)
+ {
+ skip("Failed to create activation context.\n");
+ return 1;
+ }
+
+ success = ActivateActCtx(info->handle_context, &info->cookie);
+ ok(success, "ActivateActCtx failed: %d\n", GetLastError());
+
+ info->module = LoadLibraryA("sxs_dll.dll");
+ ok(info->module != NULL, "LoadLibrary failed\n");
+
+ info->test_func = (void *)GetProcAddress(info->module, "test_func");
+ ok(info->test_func != NULL, "GetProcAddress failed\n");
+
+ DeactivateActCtx(0, info->cookie);
+ return 0;
+}
+
+static void clean_sxs_info(sxs_info *info)
+{
+ if (info->module)
+ {
+ FreeLibrary(info->module);
+ FreeLibrary(info->module); /* Make sure it's freed in any case */
+ }
+ if (info->handle_context)
+ ReleaseActCtx(info->handle_context);
+ if(*info->path_dll)
+ ok(DeleteFileA(info->path_dll), "DeleteFileA failed for %s: %d\n", info->path_dll, GetLastError());
+ if(*info->path_manifest_exe)
+ ok(DeleteFileA(info->path_manifest_exe), "DeleteFileA failed for %s: %d\n", info->path_manifest_exe, GetLastError());
+ if(*info->path_manifest_dll)
+ ok(DeleteFileA(info->path_manifest_dll), "DeleteFileA failed for %s: %d\n", info->path_manifest_dll, GetLastError());
+ if(*info->path_tmp)
+ ok(RemoveDirectoryA(info->path_tmp), "RemoveDirectoryA failed for %s: %d\n", info->path_tmp, GetLastError());
+}
+
+/* Test loading two sxs dlls at the same time */
+static void test_two_dlls_at_same_time(void)
+{
+ sxs_info dll_1 = {0};
+ sxs_info dll_2 = {0};
+ DWORD ret;
+
+ if(fill_sxs_info(&dll_1, "1", "sxs_dll_1.dll", "sxs_exe_1.manifest", "sxs_dll_1.manifest"))
+ goto cleanup;
+ if(fill_sxs_info(&dll_2, "2", "sxs_dll_2.dll", "sxs_exe_2.manifest", "sxs_dll_2.manifest"))
+ goto cleanup;
+
+ todo_wine
+ ok(dll_1.module != dll_2.module, "Libraries are the same\n");
+ ret = dll_1.test_func();
+ ok(ret == 1, "Got %d\n", ret);
+ ret = dll_2.test_func();
+ todo_wine
+ ok(ret == 2, "Got %d\n", ret);
+
+cleanup:
+ clean_sxs_info(&dll_1);
+ clean_sxs_info(&dll_2);
+}
+
+/* Test loading a normal dll and then a sxs dll with the same name */
+static void test_one_sxs_and_one_local_1(void)
+{
+ sxs_info dll = {0};
+ char path_dll_local[MAX_PATH] = {0};
+ char path_application[MAX_PATH];
+ HMODULE module = NULL;
+ DWORD(WINAPI *test_func)(void);
+ DWORD ret;
+
+ get_application_directory(path_application, sizeof(path_application));
+
+ if (!write_resource_file(path_application, "sxs_dll_2.dll", "sxs_dll.dll", path_dll_local))
+ {
+ skip("Failed to create file for testing\n");
+ goto cleanup;
+ }
+
+ module = LoadLibraryA(path_dll_local);
+ test_func = (void *)GetProcAddress(module, "test_func");
+
+ if(fill_sxs_info(&dll, "1", "sxs_dll_1.dll", "sxs_exe_1.manifest", "sxs_dll_1.manifest"))
+ goto cleanup;
+
+ todo_wine
+ ok(dll.module != module, "Libraries are the same\n");
+ ret = dll.test_func();
+ todo_wine
+ ok(ret == 1, "Got %d\n", ret);
+ ret = test_func();
+ ok(ret == 2, "Got %d\n", ret);
+
+cleanup:
+ FreeLibrary(module);
+ FreeLibrary(module); /* Make sure it's freed in any case */
+ if(*path_dll_local)
+ ok(DeleteFileA(path_dll_local), "DeleteFileA failed for %s: %d\n", path_dll_local, GetLastError());
+ clean_sxs_info(&dll);
+}
+
+/* Test if sxs dll has priority over normal dll */
+static void test_one_sxs_and_one_local_2(void)
+{
+ sxs_info dll = {0};
+ char path_dll_local[MAX_PATH] = {0};
+ char path_application[MAX_PATH];
+ HMODULE module = NULL;
+ DWORD(WINAPI *test_func)(void);
+ DWORD ret;
+
+ get_application_directory(path_application, sizeof(path_application));
+
+ if (!write_resource_file(path_application, "sxs_dll_2.dll", "sxs_dll.dll", path_dll_local))
+ {
+ skip("Failed to create file for testing\n");
+ goto cleanup;
+ }
+
+ if(fill_sxs_info(&dll, "1", "sxs_dll_1.dll", "sxs_exe_1.manifest", "sxs_dll_1.manifest"))
+ goto cleanup;
+
+ module = LoadLibraryA(path_dll_local);
+ test_func = (void *)GetProcAddress(module, "test_func");
+
+ ok(dll.module != module, "Libraries are the same\n");
+ ret = dll.test_func();
+ ok(ret == 1, "Got %d\n", ret);
+ ret = test_func();
+ ok(ret == 2, "Got %d\n", ret);
+
+cleanup:
+ FreeLibrary(module);
+ FreeLibrary(module); /* Make sure it's freed in any case */
+ if(*path_dll_local)
+ ok(DeleteFileA(path_dll_local), "DeleteFileA failed for %s: %d\n", path_dll_local, GetLastError());
+ clean_sxs_info(&dll);
+}
+
+static void run_sxs_test(int run)
+{
+ switch(run)
+ {
+ case 1:
+ test_two_dlls_at_same_time();
+ break;
+ case 2:
+ test_one_sxs_and_one_local_1();
+ break;
+ case 3:
+ test_one_sxs_and_one_local_2();
+ break;
+ }
+}
+
+static void run_child_process(int run)
+{
+ char cmdline[MAX_PATH];
+ char exe[MAX_PATH];
+ char **argv;
+ PROCESS_INFORMATION pi;
+ STARTUPINFOA si = { 0 };
+ BOOL ret;
+
+ winetest_get_mainargs( &argv );
+
+ if(strstr(argv[0], ".exe"))
+ sprintf(exe, "%s", argv[0]);
+ else
+ sprintf(exe, "%s.exe", argv[0]);
+ sprintf(cmdline, "\"%s\" %s %d", argv[0], argv[1], run);
+
+ si.cb = sizeof(si);
+ ret = CreateProcessA(exe, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ ok(ret, "Could not create process: %u\n", GetLastError());
+
+ winetest_wait_child_process( pi.hProcess );
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+}
+
+START_TEST(sxs)
+{
+ int argc;
+ char **argv;
+
+ argc = winetest_get_mainargs(&argv);
+ if(argc > 2)
+ {
+ int run = atoi(argv[2]);
+ run_sxs_test(run);
+ return;
+ }
+ run_child_process(1);
+ run_child_process(2);
+ run_child_process(3);
+}
diff --git a/dlls/kernel32/tests/sxs_dll_1.c b/dlls/kernel32/tests/sxs_dll_1.c
new file mode 100644
index 0000000000..908d235059
--- /dev/null
+++ b/dlls/kernel32/tests/sxs_dll_1.c
@@ -0,0 +1,17 @@
+#include <windows.h>
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+DWORD WINAPI test_func(void)
+{
+ return 1;
+}
diff --git a/dlls/kernel32/tests/sxs_dll_1.manifest b/dlls/kernel32/tests/sxs_dll_1.manifest
new file mode 100644
index 0000000000..61e3f4a652
--- /dev/null
+++ b/dlls/kernel32/tests/sxs_dll_1.manifest
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">
+ <assemblyIdentity type="win32" name="sxs_dll" version="1.0.0.0" processorArchitecture="x86" publicKeyToken="0000000000000000"/>
+ <file name="sxs_dll.dll">
+ <windowClass>sidebyside</windowClass>
+ </file>
+</assembly>
diff --git a/dlls/kernel32/tests/sxs_dll_1.spec b/dlls/kernel32/tests/sxs_dll_1.spec
new file mode 100644
index 0000000000..ebbc584352
--- /dev/null
+++ b/dlls/kernel32/tests/sxs_dll_1.spec
@@ -0,0 +1 @@
+@ stdcall test_func()
diff --git a/dlls/kernel32/tests/sxs_dll_2.c b/dlls/kernel32/tests/sxs_dll_2.c
new file mode 100644
index 0000000000..262c53a484
--- /dev/null
+++ b/dlls/kernel32/tests/sxs_dll_2.c
@@ -0,0 +1,17 @@
+#include <windows.h>
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+DWORD WINAPI test_func(void)
+{
+ return 2;
+}
diff --git a/dlls/kernel32/tests/sxs_dll_2.manifest b/dlls/kernel32/tests/sxs_dll_2.manifest
new file mode 100644
index 0000000000..37b39bea3b
--- /dev/null
+++ b/dlls/kernel32/tests/sxs_dll_2.manifest
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">
+ <assemblyIdentity type="win32" name="sxs_dll" version="2.0.0.0" processorArchitecture="x86" publicKeyToken="0000000000000000"/>
+ <file name="sxs_dll.dll">
+ <windowClass>sidebyside</windowClass>
+ </file>
+</assembly>
diff --git a/dlls/kernel32/tests/sxs_dll_2.spec b/dlls/kernel32/tests/sxs_dll_2.spec
new file mode 100644
index 0000000000..ebbc584352
--- /dev/null
+++ b/dlls/kernel32/tests/sxs_dll_2.spec
@@ -0,0 +1 @@
+@ stdcall test_func()
diff --git a/dlls/kernel32/tests/sxs_exe_1.manifest b/dlls/kernel32/tests/sxs_exe_1.manifest
new file mode 100644
index 0000000000..633374eca3
--- /dev/null
+++ b/dlls/kernel32/tests/sxs_exe_1.manifest
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type="win32" name="sxs_dll" version="1.0.0.0" processorArchitecture="x86" publicKeyToken="0000000000000000" language="*"/>
+ </dependentAssembly>
+ </dependency>
+</assembly>
diff --git a/dlls/kernel32/tests/sxs_exe_2.manifest b/dlls/kernel32/tests/sxs_exe_2.manifest
new file mode 100644
index 0000000000..f93e497124
--- /dev/null
+++ b/dlls/kernel32/tests/sxs_exe_2.manifest
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type="win32" name="sxs_dll" version="2.0.0.0" processorArchitecture="x86" publicKeyToken="0000000000000000" language="*"/>
+ </dependentAssembly>
+ </dependency>
+</assembly>
--
2.21.0