Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43270 Signed-off-by: Fabian Maurer dark.shadow4@web.de --- v5: check for admin rights before trying to write into system32 fix test failure on xp. dll can't be in same folder as manifest give test runs better names v6: Fix test failure by compiling into temp folder and then moving file --- dlls/mscoree/tests/Makefile.in | 6 +- dlls/mscoree/tests/comtest.c | 356 ++++++++++++++++++++++++ dlls/mscoree/tests/comtest.cs | 23 ++ dlls/mscoree/tests/comtest_dll.manifest | 16 ++ dlls/mscoree/tests/comtest_exe.manifest | 11 + dlls/mscoree/tests/interfaces.idl | 33 +++ dlls/mscoree/tests/resource.rc | 30 ++ 7 files changed, 474 insertions(+), 1 deletion(-) create mode 100644 dlls/mscoree/tests/comtest.c create mode 100644 dlls/mscoree/tests/comtest.cs create mode 100644 dlls/mscoree/tests/comtest_dll.manifest create mode 100644 dlls/mscoree/tests/comtest_exe.manifest create mode 100644 dlls/mscoree/tests/interfaces.idl create mode 100644 dlls/mscoree/tests/resource.rc
diff --git a/dlls/mscoree/tests/Makefile.in b/dlls/mscoree/tests/Makefile.in index 7c1ba5cb11..f65e1bc6c2 100644 --- a/dlls/mscoree/tests/Makefile.in +++ b/dlls/mscoree/tests/Makefile.in @@ -1,7 +1,11 @@ TESTDLL = mscoree.dll -IMPORTS = ole32 shlwapi uuid +IMPORTS = ole32 shlwapi uuid shell32
C_SRCS = \ + comtest.c \ debugging.c \ metahost.c \ mscoree.c + +RC_SRCS = resource.rc +IDL_SRCS = interfaces.idl diff --git a/dlls/mscoree/tests/comtest.c b/dlls/mscoree/tests/comtest.c new file mode 100644 index 0000000000..e9812eb6b9 --- /dev/null +++ b/dlls/mscoree/tests/comtest.c @@ -0,0 +1,356 @@ +/* + * Copyright 2018 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 + */ + +#define COBJMACROS +#include <stdio.h> + +#include "windows.h" +#include "ole2.h" +#include "mscoree.h" +#include "corerror.h" +#include "shlwapi.h" +#include "shlobj.h" + +#include "wine/test.h" + +#include "initguid.h" +#include "interfaces.h" + +HMODULE hmscoree; + +typedef enum _run_type +{ + run_type_current_working_directory = 0, + run_type_exe_directory, + run_type_system32, +} run_type; + +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) 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; + + strcpy(path_file, path_tmp); + PathAppendA(path_file, 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 BOOL compile_cs_to_dll(char *source_path, char *dest_path) +{ + const char *path_csc = "C:\windows\Microsoft.NET\Framework\v2.0.50727\csc.exe"; + char cmdline[MAX_PATH]; + char path_temp[MAX_PATH] = {0}; + PROCESS_INFORMATION pi; + STARTUPINFOA si = { 0 }; + BOOL ret; + + if (!PathFileExistsA(path_csc)) + { + skip("Can't find csc.exe\n"); + return FALSE; + } + + GetTempPathA(MAX_PATH, path_temp); + PathAppendA(path_temp, "comtest.dll"); + + sprintf(cmdline, "%s /t:library /out:"%s" "%s"", path_csc, path_temp, source_path); + + si.cb = sizeof(si); + ret = CreateProcessA(path_csc, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + ok(ret, "Could not create process: %u\n", GetLastError()); + + WaitForSingleObject(pi.hProcess, 5000); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + + ret = PathFileExistsA(path_temp); + ok(ret, "Compilation failed\n"); + + ret = MoveFileA(path_temp, dest_path); + ok(ret, "Moving temporary file failed\n"); + return ret; +} + +static void run_test(BOOL expect_success) +{ + typedef HRESULT (WINAPI *_DllGetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID *ppv); + ITest *test = NULL; + HRESULT hr; + _DllGetClassObject getClassObject; + IClassFactory *classFactory = NULL; + HRESULT result_expected = expect_success ? S_OK : HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + + hr = CoCreateInstance(&CLSID_Test, NULL, CLSCTX_INPROC_SERVER, &IID_ITest, (void**)&test); + todo_wine + ok(hr == result_expected, "Expected %x, got %x\n", result_expected, hr); + + if (hr == S_OK) + { + int i = 0; + hr = ITest_Func(test, &i); + ok(hr == S_OK, "Got %x\n", hr); + ok(i == 42, "Expected 42, got %d\n", i); + ITest_Release(test); + } + + getClassObject = (_DllGetClassObject)GetProcAddress(hmscoree, "DllGetClassObject"); + hr = getClassObject(&CLSID_Test, &IID_IClassFactory, (void **)&classFactory); + todo_wine_if(!expect_success) + ok(hr == result_expected, "Expected %x, got %x\n", result_expected, hr); + + if (hr == S_OK) + { + ITest *test2 = NULL; + hr = IClassFactory_CreateInstance(classFactory, NULL, &IID_ITest, (void **)&test2); + todo_wine + ok(hr == S_OK, "Got %x\n", hr); + + if (hr == S_OK) + { + int i = 0; + hr = ITest_Func(test2, &i); + ok(hr == S_OK, "Got %x\n", hr); + ok(i == 42, "Expected 42, got %d\n", i); + ITest_Release(test2); + } + IClassFactory_Release(classFactory); + } +} + +static void get_dll_path_for_run(char *path_dll, UINT path_dll_size, run_type run) +{ + char path_tmp[MAX_PATH] = {0}; + + GetTempPathA(MAX_PATH, path_tmp); + + switch (run) + { + case run_type_current_working_directory: + strcpy(path_dll, path_tmp); + PathAppendA(path_dll, "comtest.dll"); + break; + case run_type_exe_directory: + GetModuleFileNameA(NULL, path_dll, path_dll_size); + PathRemoveFileSpecA(path_dll); + PathAppendA(path_dll, "comtest.dll"); + break; + case run_type_system32: + GetSystemDirectoryA(path_dll, path_dll_size); + PathAppendA(path_dll, "comtest.dll"); + break; + } +} +static void prepare_and_run_test(const char *dll_source, run_type run) +{ + char path_tmp[MAX_PATH] = {0}; + char path_tmp_manifest[MAX_PATH] = {0}; + char path_dll[MAX_PATH] = {0}; + char path_dll_source[MAX_PATH] = {0}; + char path_manifest_dll[MAX_PATH] = {0}; + char path_manifest_exe[MAX_PATH] = {0}; + BOOL success; + ACTCTXA context = {0}; + ULONG_PTR cookie; + HANDLE handle_context = 0; + + GetTempPathA(MAX_PATH, path_tmp); + GetTempPathA(MAX_PATH, path_tmp_manifest); + PathAppendA(path_tmp_manifest, "manifests"); + + CreateDirectoryA(path_tmp_manifest, NULL); + + if (run == run_type_system32) + { + if (!IsUserAnAdmin()) + { + skip("Can't test dll in system32 due to user not being admin.\n"); + return; + } + } + + if (!write_resource_file(path_tmp, dll_source, "comtest.cs", path_dll_source)) + { + ok(0, "run: %d, Failed to create file for testing\n", run); + goto cleanup; + } + + get_dll_path_for_run(path_dll, sizeof(path_dll), run); + + if (!compile_cs_to_dll(path_dll_source, path_dll)) + goto cleanup; + + if (!write_resource_file(path_tmp_manifest, "comtest_exe.manifest", "exe.manifest", path_manifest_exe)) + { + ok(0, "run: %d, Failed to create file for testing\n", run); + goto cleanup; + } + + if (!write_resource_file(path_tmp_manifest, "comtest_dll.manifest", "comtest.manifest", path_manifest_dll)) + { + ok(0, "run: %d, Failed to create file for testing\n", run); + goto cleanup; + } + + context.cbSize = sizeof(ACTCTXA); + context.lpSource = path_manifest_exe; + context.lpAssemblyDirectory = path_tmp_manifest; + context.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; + + handle_context = CreateActCtxA(&context); + ok(handle_context != NULL && handle_context != INVALID_HANDLE_VALUE, "run: %d, CreateActCtxA failed: %d\n", run, GetLastError()); + + if (handle_context == NULL || handle_context == INVALID_HANDLE_VALUE) + { + ok(0, "run: %d, Failed to create activation context\n", run); + goto cleanup; + } + + success = ActivateActCtx(handle_context, &cookie); + ok(success, "run: %d, ActivateActCtx failed: %d\n", run, GetLastError()); + + if (run == run_type_current_working_directory) + SetCurrentDirectoryA(path_tmp); + + run_test(run == run_type_exe_directory); + +cleanup: + if (handle_context != NULL && handle_context != INVALID_HANDLE_VALUE) + { + success = DeactivateActCtx(0, cookie); + ok(success, "run: %d, DeactivateActCtx failed: %d\n", run, GetLastError()); + ReleaseActCtx(handle_context); + } + if (*path_manifest_exe) + { + success = DeleteFileA(path_manifest_exe); + ok(success, "run: %d, DeleteFileA failed: %d\n", run, GetLastError()); + } + if(*path_manifest_dll) + { + success = DeleteFileA(path_manifest_dll); + ok(success, "run: %d, DeleteFileA failed: %d\n", run, GetLastError()); + } + if(*path_dll_source) + { + success = DeleteFileA(path_dll_source); + ok(success, "run: %d, DeleteFileA failed: %d\n", run, GetLastError()); + } + RemoveDirectoryA(path_tmp_manifest); + /* dll cleanup is handled by the parent, because it might still be used by the child */ +} + + +static void cleanup_test(run_type run) +{ + char path_dll[MAX_PATH] = {0}; + BOOL success; + + get_dll_path_for_run(path_dll, sizeof(path_dll), run); + + if (!PathFileExistsA(path_dll)) + return; + + success = DeleteFileA(path_dll); + if (!success) + { + Sleep(500); + success = DeleteFileA(path_dll); + } + ok(success, "DeleteFileA failed: %d\n", GetLastError()); +} + +static void run_child_process(const char *dll_source, run_type 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 %s %d", argv[0], argv[1], dll_source, 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); + + /* Cleanup dll, because it might still have been used by the child */ + cleanup_test(run); +} + +START_TEST(comtest) +{ + int argc; + char **argv; + + CoInitialize(NULL); + + hmscoree = LoadLibraryA("mscoree.dll"); + if (!hmscoree) + { + skip(".NET or mono not available\n"); + return; + } + + argc = winetest_get_mainargs(&argv); + if (argc > 2) + { + const char *dll_source = argv[2]; + run_type run = atoi(argv[3]); + prepare_and_run_test(dll_source, run); + + goto cleanup; + } + + run_child_process("comtest.cs", run_type_current_working_directory); + run_child_process("comtest.cs", run_type_exe_directory); + run_child_process("comtest.cs", run_type_system32); + +cleanup: + FreeLibrary(hmscoree); + CoUninitialize(); +} diff --git a/dlls/mscoree/tests/comtest.cs b/dlls/mscoree/tests/comtest.cs new file mode 100644 index 0000000000..4fe2a718b2 --- /dev/null +++ b/dlls/mscoree/tests/comtest.cs @@ -0,0 +1,23 @@ +/* Compile with + csc /target:library /out:dll.dll comtest.cs +*/ + +using System.Runtime.InteropServices; + +namespace DLL +{ + [Guid("1dbc4491-080d-45c5-a15d-1e3c4610bdd9"), ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface ITest + { + void Func(ref int i); + } + + [Guid("2e106e50-e7a4-4489-8538-83643f100fdc"), ComVisible(true), ClassInterface(ClassInterfaceType.None)] + public class Test : ITest + { + public void Func(ref int i) + { + i = 42; + } + } +} diff --git a/dlls/mscoree/tests/comtest_dll.manifest b/dlls/mscoree/tests/comtest_dll.manifest new file mode 100644 index 0000000000..ef6924de9e --- /dev/null +++ b/dlls/mscoree/tests/comtest_dll.manifest @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity + name="comtest" + version="1.0.0.0" + type="win32" + /> + <clrClass + clsid="{2e106e50-e7a4-4489-8538-83643f100fdc}" + threadingModel="Both" + name="DLL.Test" + runtimeVersion="v4.0.0.0"> + </clrClass> + <file name="comtest.dll"> + </file> +</assembly> diff --git a/dlls/mscoree/tests/comtest_exe.manifest b/dlls/mscoree/tests/comtest_exe.manifest new file mode 100644 index 0000000000..bc9ce4c045 --- /dev/null +++ b/dlls/mscoree/tests/comtest_exe.manifest @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <dependency> + <dependentAssembly> + <assemblyIdentity + name="comtest" + version="1.0.0.0" + type="win32"/> + </dependentAssembly> + </dependency> +</assembly> diff --git a/dlls/mscoree/tests/interfaces.idl b/dlls/mscoree/tests/interfaces.idl new file mode 100644 index 0000000000..9e64988197 --- /dev/null +++ b/dlls/mscoree/tests/interfaces.idl @@ -0,0 +1,33 @@ +/* + * Copyright 2018 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 "unknwn.idl" + +[ + object, + uuid(1dbc4491-080d-45c5-a15d-1e3c4610bdd9), + local +] +interface ITest : IUnknown { + HRESULT Func([in, out] int *i); +}; + +[ + uuid(2e106e50-e7a4-4489-8538-83643f100fdc), +] +coclass Test { interface ITest; }; diff --git a/dlls/mscoree/tests/resource.rc b/dlls/mscoree/tests/resource.rc new file mode 100644 index 0000000000..9a1b89f656 --- /dev/null +++ b/dlls/mscoree/tests/resource.rc @@ -0,0 +1,30 @@ +/* + * Resources for mscoree test suite. + * + * Copyright 2018 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 "windef.h" + +/* @makedep: comtest.cs */ +comtest.cs RCDATA comtest.cs + +/* @makedep: comtest_exe.manifest */ +comtest_exe.manifest RCDATA comtest_exe.manifest + +/* @makedep: comtest_dll.manifest */ +comtest_dll.manifest RCDATA comtest_dll.manifest
Signed-off-by: Fabian Maurer dark.shadow4@web.de --- dlls/mscoree/corruntimehost.c | 219 ++++++++++++++++++++++++---------- dlls/mscoree/tests/comtest.c | 4 +- 2 files changed, 160 insertions(+), 63 deletions(-)
diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c index 5c4e7f1d6e..ef4685822d 100644 --- a/dlls/mscoree/corruntimehost.c +++ b/dlls/mscoree/corruntimehost.c @@ -29,6 +29,7 @@ #include "winreg.h" #include "ole2.h" #include "shellapi.h" +#include "shlwapi.h"
#include "cor.h" #include "mscoree.h" @@ -40,6 +41,7 @@
#include "wine/debug.h" #include "wine/unicode.h" +#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
@@ -68,6 +70,43 @@ struct dll_fixup void *tokens; /* pointer into process heap */ };
+struct comclassredirect_data +{ + ULONG size; + BYTE res; + BYTE miscmask; + BYTE res1[2]; + DWORD model; + GUID clsid; + GUID alias; + GUID clsid2; + GUID tlbid; + ULONG name_len; + ULONG name_offset; + ULONG progid_len; + ULONG progid_offset; + ULONG clrdata_len; + ULONG clrdata_offset; + DWORD miscstatus; + DWORD miscstatuscontent; + DWORD miscstatusthumbnail; + DWORD miscstatusicon; + DWORD miscstatusdocprint; +}; + +struct clrclass_data +{ + ULONG size; + DWORD res[2]; + ULONG module_len; + ULONG module_offset; + ULONG name_len; + ULONG name_offset; + ULONG version_len; + ULONG version_offset; + DWORD res2[2]; +}; + static MonoDomain* domain_attach(MonoDomain *domain) { MonoDomain *prev_domain = mono_domain_get(); @@ -1606,6 +1645,57 @@ HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, return CLASS_E_CLASSNOTAVAILABLE; }
+static BOOL try_create_registration_free_com(REFIID clsid, WCHAR *classname, WCHAR *filename, UINT filename_size) +{ + ACTCTX_SECTION_KEYED_DATA guid_info = { sizeof(ACTCTX_SECTION_KEYED_DATA) }; + ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *assembly_info; + SIZE_T bytes_assembly_info; + struct comclassredirect_data *redirect_data; + struct clrclass_data *class_data; + void *ptr_name; + const WCHAR *ptr_path_start, *ptr_path_end; + WCHAR path[MAX_PATH] = {0}; + WCHAR str_dll[] = {'.','d','l','l',0}; + + if (!FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, 0, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, clsid, &guid_info)) + { + DWORD error = GetLastError(); + if (error != ERROR_SXS_KEY_NOT_FOUND) + ERR("Failed to find guid: %d\n", error); + return FALSE; + } + + QueryActCtxW(0, guid_info.hActCtx, &guid_info.ulAssemblyRosterIndex, AssemblyDetailedInformationInActivationContext, NULL, 0, &bytes_assembly_info); + assembly_info = heap_alloc(bytes_assembly_info); + if (!QueryActCtxW(0, guid_info.hActCtx, &guid_info.ulAssemblyRosterIndex, + AssemblyDetailedInformationInActivationContext, assembly_info, bytes_assembly_info, &bytes_assembly_info)) + { + ERR("QueryActCtxW failed: %d!\n", GetLastError()); + heap_free(assembly_info); + ReleaseActCtx(guid_info.hActCtx); + return FALSE; + } + + redirect_data = guid_info.lpData; + class_data = (void *)((char*)redirect_data + redirect_data->clrdata_offset); + + ptr_name = (char *)class_data + class_data->name_offset; + strcpyW(classname, ptr_name); + + ptr_path_start = assembly_info->lpAssemblyEncodedAssemblyIdentity; + ptr_path_end = strchrW(ptr_path_start, ','); + memcpy(path, ptr_path_start, (char*)ptr_path_end - (char*)ptr_path_start); + + GetModuleFileNameW(NULL, filename, filename_size); + PathRemoveFileSpecW(filename); + PathAppendW(filename, path); + strcatW(filename, str_dll); + + heap_free(assembly_info); + ReleaseActCtx(guid_info.hActCtx); + return TRUE; +} + #define CHARS_IN_GUID 39
HRESULT create_monodata(REFIID riid, LPVOID *ppObj ) @@ -1640,75 +1730,82 @@ HRESULT create_monodata(REFIID riid, LPVOID *ppObj ) TRACE("Registry key: %s\n", debugstr_w(path));
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &key); - if (res == ERROR_FILE_NOT_FOUND) - return CLASS_E_CLASSNOTAVAILABLE; - - res = RegGetValueW( key, NULL, wszClass, RRF_RT_REG_SZ, NULL, classname, &dwBufLen); - if(res != ERROR_SUCCESS) + if (res != ERROR_FILE_NOT_FOUND) { - WARN("Class value cannot be found.\n"); - hr = CLASS_E_CLASSNOTAVAILABLE; - goto cleanup; - } + res = RegGetValueW( key, NULL, wszClass, RRF_RT_REG_SZ, NULL, classname, &dwBufLen); + if(res != ERROR_SUCCESS) + { + WARN("Class value cannot be found.\n"); + hr = CLASS_E_CLASSNOTAVAILABLE; + goto cleanup; + }
- TRACE("classname (%s)\n", debugstr_w(classname)); + TRACE("classname (%s)\n", debugstr_w(classname));
- dwBufLen = MAX_PATH + 8; - res = RegGetValueW( key, NULL, wszCodebase, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen); - if(res == ERROR_SUCCESS) - { - /* Strip file:/// */ - if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0) - offset = strlenW(wszFileSlash); + dwBufLen = MAX_PATH + 8; + res = RegGetValueW( key, NULL, wszCodebase, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen); + if(res == ERROR_SUCCESS) + { + /* Strip file:/// */ + if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0) + offset = strlenW(wszFileSlash); + + strcpyW(filename, codebase + offset); + } + else + { + WCHAR assemblyname[MAX_PATH + 8];
- strcpyW(filename, codebase + offset); + hr = CLASS_E_CLASSNOTAVAILABLE; + WARN("CodeBase value cannot be found, trying Assembly.\n"); + /* get the last subkey of InprocServer32 */ + res = RegQueryInfoKeyW(key, 0, 0, 0, &numKeys, 0, 0, 0, 0, 0, 0, 0); + if (res != ERROR_SUCCESS || numKeys == 0) + goto cleanup; + numKeys--; + keyLength = ARRAY_SIZE(subkeyName); + res = RegEnumKeyExW(key, numKeys, subkeyName, &keyLength, 0, 0, 0, 0); + if (res != ERROR_SUCCESS) + goto cleanup; + res = RegOpenKeyExW(key, subkeyName, 0, KEY_READ, &subkey); + if (res != ERROR_SUCCESS) + goto cleanup; + dwBufLen = MAX_PATH + 8; + res = RegGetValueW(subkey, NULL, wszAssembly, RRF_RT_REG_SZ, NULL, assemblyname, &dwBufLen); + RegCloseKey(subkey); + if (res != ERROR_SUCCESS) + goto cleanup; + + hr = get_file_from_strongname(assemblyname, filename, MAX_PATH); + if (FAILED(hr)) + { + /* + * The registry doesn't have a CodeBase entry and it's not in the GAC. + * + * Use the Assembly Key to retrieve the filename. + * Assembly : REG_SZ : AssemblyName, Version=X.X.X.X, Culture=neutral, PublicKeyToken=null + */ + WCHAR *ns; + + WARN("Attempt to load from the application directory.\n"); + GetModuleFileNameW(NULL, filename, MAX_PATH); + ns = strrchrW(filename, '\'); + *(ns+1) = '\0'; + + ns = strchrW(assemblyname, ','); + *(ns) = '\0'; + strcatW(filename, assemblyname); + *(ns) = '.'; + strcatW(filename, wszDLL); + } + } } else { - WCHAR assemblyname[MAX_PATH + 8]; - - hr = CLASS_E_CLASSNOTAVAILABLE; - WARN("CodeBase value cannot be found, trying Assembly.\n"); - /* get the last subkey of InprocServer32 */ - res = RegQueryInfoKeyW(key, 0, 0, 0, &numKeys, 0, 0, 0, 0, 0, 0, 0); - if (res != ERROR_SUCCESS || numKeys == 0) - goto cleanup; - numKeys--; - keyLength = ARRAY_SIZE(subkeyName); - res = RegEnumKeyExW(key, numKeys, subkeyName, &keyLength, 0, 0, 0, 0); - if (res != ERROR_SUCCESS) - goto cleanup; - res = RegOpenKeyExW(key, subkeyName, 0, KEY_READ, &subkey); - if (res != ERROR_SUCCESS) - goto cleanup; - dwBufLen = MAX_PATH + 8; - res = RegGetValueW(subkey, NULL, wszAssembly, RRF_RT_REG_SZ, NULL, assemblyname, &dwBufLen); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) - goto cleanup; + if (!try_create_registration_free_com(riid, classname, filename, sizeof(filename))) + return CLASS_E_CLASSNOTAVAILABLE;
- hr = get_file_from_strongname(assemblyname, filename, MAX_PATH); - if (FAILED(hr)) - { - /* - * The registry doesn't have a CodeBase entry and it's not in the GAC. - * - * Use the Assembly Key to retrieve the filename. - * Assembly : REG_SZ : AssemblyName, Version=X.X.X.X, Culture=neutral, PublicKeyToken=null - */ - WCHAR *ns; - - WARN("Attempt to load from the application directory.\n"); - GetModuleFileNameW(NULL, filename, MAX_PATH); - ns = strrchrW(filename, '\'); - *(ns+1) = '\0'; - - ns = strchrW(assemblyname, ','); - *(ns) = '\0'; - strcatW(filename, assemblyname); - *(ns) = '.'; - strcatW(filename, wszDLL); - } + TRACE("classname (%s)\n", debugstr_w(classname)); }
TRACE("filename (%s)\n", debugstr_w(filename)); diff --git a/dlls/mscoree/tests/comtest.c b/dlls/mscoree/tests/comtest.c index e9812eb6b9..bd1632300a 100644 --- a/dlls/mscoree/tests/comtest.c +++ b/dlls/mscoree/tests/comtest.c @@ -114,7 +114,7 @@ static void run_test(BOOL expect_success) HRESULT result_expected = expect_success ? S_OK : HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
hr = CoCreateInstance(&CLSID_Test, NULL, CLSCTX_INPROC_SERVER, &IID_ITest, (void**)&test); - todo_wine + todo_wine_if(!expect_success) ok(hr == result_expected, "Expected %x, got %x\n", result_expected, hr);
if (hr == S_OK) @@ -135,7 +135,7 @@ static void run_test(BOOL expect_success) { ITest *test2 = NULL; hr = IClassFactory_CreateInstance(classFactory, NULL, &IID_ITest, (void **)&test2); - todo_wine + todo_wine_if(!expect_success) ok(hr == S_OK, "Got %x\n", hr);
if (hr == S_OK)
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43270 Signed-off-by: Fabian Maurer dark.shadow4@web.de --- dlls/sxs/sxs.c | 148 ++++++++++++++++++ dlls/sxs/sxs.spec | 1 + dlls/sxs/tests/Makefile.in | 8 +- dlls/sxs/tests/comtest_dll.manifest | 16 ++ dlls/sxs/tests/comtest_exe.manifest | 11 ++ dlls/sxs/tests/interfaces.idl | 33 ++++ dlls/sxs/tests/resource.rc | 27 ++++ dlls/sxs/tests/sxs.c | 223 ++++++++++++++++++++++++++++ 8 files changed, 465 insertions(+), 2 deletions(-) create mode 100644 dlls/sxs/tests/comtest_dll.manifest create mode 100644 dlls/sxs/tests/comtest_exe.manifest create mode 100644 dlls/sxs/tests/interfaces.idl create mode 100644 dlls/sxs/tests/resource.rc create mode 100644 dlls/sxs/tests/sxs.c
diff --git a/dlls/sxs/sxs.c b/dlls/sxs/sxs.c index 06e6672dbf..7eec772de1 100644 --- a/dlls/sxs/sxs.c +++ b/dlls/sxs/sxs.c @@ -23,6 +23,10 @@ #include "windef.h" #include "winbase.h"
+#include "wine/heap.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(sxs);
/*********************************************************************** * DllMain (SXS.@) @@ -40,3 +44,147 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) } return TRUE; } + +typedef struct _SXS_GUID_INFORMATION_CLR +{ + DWORD cbSize; + DWORD dwFlags; + PCWSTR pcwszRuntimeVersion; + PCWSTR pcwszTypeName; + PCWSTR pcwszAssemblyIdentity; +} SXS_GUID_INFORMATION_CLR, *PSXS_GUID_INFORMATION_CLR; + +#define SXS_GUID_INFORMATION_CLR_FLAG_IS_SURROGATE 0x1 +#define SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS 0x2 + +#define SXS_LOOKUP_CLR_GUID_USE_ACTCTX 0x00000001 +#define SXS_LOOKUP_CLR_GUID_FIND_SURROGATE 0x00010000 +#define SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS 0x00020000 + +struct comclassredirect_data +{ + ULONG size; + BYTE res; + BYTE miscmask; + BYTE res1[2]; + DWORD model; + GUID clsid; + GUID alias; + GUID clsid2; + GUID tlbid; + ULONG name_len; + ULONG name_offset; + ULONG progid_len; + ULONG progid_offset; + ULONG clrdata_len; + ULONG clrdata_offset; + DWORD miscstatus; + DWORD miscstatuscontent; + DWORD miscstatusthumbnail; + DWORD miscstatusicon; + DWORD miscstatusdocprint; +}; + +struct clrclass_data +{ + ULONG size; + DWORD res[2]; + ULONG module_len; + ULONG module_offset; + ULONG name_len; + ULONG name_offset; + ULONG version_len; + ULONG version_offset; + DWORD res2[2]; +}; + +BOOL WINAPI SxsLookupClrGuid(DWORD flags, GUID *clsid, HANDLE actctx, void *buffer, SIZE_T buffer_len, SIZE_T *buffer_len_required) +{ + ACTCTX_SECTION_KEYED_DATA guid_info = { sizeof(ACTCTX_SECTION_KEYED_DATA) }; + ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *assembly_info; + SIZE_T bytes_assembly_info; + struct comclassredirect_data *redirect_data; + struct clrclass_data *class_data; + int len_version = 0, len_name, len_identity; + const void *ptr_name, *ptr_version, *ptr_identity; + SXS_GUID_INFORMATION_CLR *ret = buffer; + char *ret_strings; + + TRACE("(%x, %s, %p, %p, %08lx, %p): stub\n", flags, wine_dbgstr_guid(clsid), actctx, buffer, buffer_len, buffer_len_required); + + if (flags & (~SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS)) + FIXME("Ignored flags: %x\n", flags & (~SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS)); + + if (!FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, 0, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, clsid, &guid_info)) + { + SetLastError(ERROR_NOT_FOUND); + return FALSE; + } + + QueryActCtxW(0, guid_info.hActCtx, &guid_info.ulAssemblyRosterIndex, + AssemblyDetailedInformationInActivationContext, NULL, 0, &bytes_assembly_info); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + ERR("QueryActCtxW failed: %d!\n", GetLastError()); + ReleaseActCtx(guid_info.hActCtx); + return FALSE; + } + assembly_info = heap_alloc(bytes_assembly_info); + if(!QueryActCtxW(0, guid_info.hActCtx, &guid_info.ulAssemblyRosterIndex, + AssemblyDetailedInformationInActivationContext, assembly_info, bytes_assembly_info, &bytes_assembly_info)) + { + ERR("QueryActCtxW failed: %d!\n", GetLastError()); + heap_free(assembly_info); + ReleaseActCtx(guid_info.hActCtx); + return FALSE; + } + + redirect_data = guid_info.lpData; + class_data = (void *)((char*)redirect_data + redirect_data->clrdata_offset); + + ptr_identity = assembly_info->lpAssemblyEncodedAssemblyIdentity; + ptr_name = (char *)class_data + class_data->name_offset; + ptr_version = (char *)class_data + class_data->version_offset; + + len_identity = assembly_info->ulEncodedAssemblyIdentityLength + sizeof(WCHAR); + len_name = class_data->name_len + sizeof(WCHAR); + if (class_data->version_len > 0) + len_version = class_data->version_len + sizeof(WCHAR); + + *buffer_len_required = sizeof(SXS_GUID_INFORMATION_CLR) + len_identity + len_version + len_name; + if (!buffer || buffer_len < *buffer_len_required) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + heap_free(assembly_info); + ReleaseActCtx(guid_info.hActCtx); + return FALSE; + } + + ret->cbSize = sizeof(SXS_GUID_INFORMATION_CLR); + ret->dwFlags = SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS; + + /* Copy strings into buffer */ + ret_strings = (char *)ret + sizeof(SXS_GUID_INFORMATION_CLR); + + memcpy(ret_strings, ptr_identity, len_identity); + ret->pcwszAssemblyIdentity = (WCHAR *)ret_strings; + ret_strings += len_identity; + + memcpy(ret_strings, ptr_name, len_name); + ret->pcwszTypeName = (WCHAR *)ret_strings; + ret_strings += len_name; + + if (len_version > 0) + { + memcpy(ret_strings, ptr_version, len_version); + ret->pcwszRuntimeVersion = (WCHAR *)ret_strings; + } + else + ret->pcwszRuntimeVersion = NULL; + + SetLastError(0); + + ReleaseActCtx(guid_info.hActCtx); + heap_free(assembly_info); + return TRUE; +} diff --git a/dlls/sxs/sxs.spec b/dlls/sxs/sxs.spec index 2a27313427..138d68f7d7 100644 --- a/dlls/sxs/sxs.spec +++ b/dlls/sxs/sxs.spec @@ -1,2 +1,3 @@ @ stdcall CreateAssemblyCache(ptr long) @ stdcall CreateAssemblyNameObject(ptr wstr long ptr) +@ stdcall SxsLookupClrGuid(long ptr ptr ptr long ptr) diff --git a/dlls/sxs/tests/Makefile.in b/dlls/sxs/tests/Makefile.in index 34609a14ae..46b5485d29 100644 --- a/dlls/sxs/tests/Makefile.in +++ b/dlls/sxs/tests/Makefile.in @@ -1,6 +1,10 @@ TESTDLL = sxs.dll -IMPORTS = sxs +IMPORTS = sxs shlwapi
C_SRCS = \ cache.c \ - name.c + name.c \ + sxs.c + +RC_SRCS = resource.rc +IDL_SRCS = interfaces.idl \ No newline at end of file diff --git a/dlls/sxs/tests/comtest_dll.manifest b/dlls/sxs/tests/comtest_dll.manifest new file mode 100644 index 0000000000..ef6924de9e --- /dev/null +++ b/dlls/sxs/tests/comtest_dll.manifest @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity + name="comtest" + version="1.0.0.0" + type="win32" + /> + <clrClass + clsid="{2e106e50-e7a4-4489-8538-83643f100fdc}" + threadingModel="Both" + name="DLL.Test" + runtimeVersion="v4.0.0.0"> + </clrClass> + <file name="comtest.dll"> + </file> +</assembly> diff --git a/dlls/sxs/tests/comtest_exe.manifest b/dlls/sxs/tests/comtest_exe.manifest new file mode 100644 index 0000000000..bc9ce4c045 --- /dev/null +++ b/dlls/sxs/tests/comtest_exe.manifest @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <dependency> + <dependentAssembly> + <assemblyIdentity + name="comtest" + version="1.0.0.0" + type="win32"/> + </dependentAssembly> + </dependency> +</assembly> diff --git a/dlls/sxs/tests/interfaces.idl b/dlls/sxs/tests/interfaces.idl new file mode 100644 index 0000000000..9e64988197 --- /dev/null +++ b/dlls/sxs/tests/interfaces.idl @@ -0,0 +1,33 @@ +/* + * Copyright 2018 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 "unknwn.idl" + +[ + object, + uuid(1dbc4491-080d-45c5-a15d-1e3c4610bdd9), + local +] +interface ITest : IUnknown { + HRESULT Func([in, out] int *i); +}; + +[ + uuid(2e106e50-e7a4-4489-8538-83643f100fdc), +] +coclass Test { interface ITest; }; diff --git a/dlls/sxs/tests/resource.rc b/dlls/sxs/tests/resource.rc new file mode 100644 index 0000000000..dd2c25bf37 --- /dev/null +++ b/dlls/sxs/tests/resource.rc @@ -0,0 +1,27 @@ +/* + * Resources for sxs test suite. + * + * Copyright 2018 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 "windef.h" + +/* @makedep: comtest_exe.manifest */ +comtest_exe.manifest RCDATA comtest_exe.manifest + +/* @makedep: comtest_dll.manifest */ +comtest_dll.manifest RCDATA comtest_dll.manifest diff --git a/dlls/sxs/tests/sxs.c b/dlls/sxs/tests/sxs.c new file mode 100644 index 0000000000..d92bfb65c1 --- /dev/null +++ b/dlls/sxs/tests/sxs.c @@ -0,0 +1,223 @@ +/* + * Copyright 2018 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 <stdio.h> + +#define COBJMACROS + +#include <windows.h> +#include <winsxs.h> +#include <corerror.h> +#include "shlwapi.h" + +#include "wine/test.h" +#include "wine/heap.h" + +#include "initguid.h" +#include "interfaces.h" + +BOOL (WINAPI *pSxsLookupClrGuid)(DWORD flags, GUID *clsid, HANDLE actctx, void *buffer, SIZE_T buffer_len, SIZE_T *buffer_len_required); + +#define SXS_LOOKUP_CLR_GUID_USE_ACTCTX 0x00000001 +#define SXS_LOOKUP_CLR_GUID_FIND_SURROGATE 0x00010000 +#define SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS 0x00020000 +#define SXS_LOOKUP_CLR_GUID_FIND_ANY (SXS_LOOKUP_CLR_GUID_FIND_SURROGATE | SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS) + +#define SXS_GUID_INFORMATION_CLR_FLAG_IS_SURROGATE 0x00000001 +#define SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS 0x00000002 + +typedef struct _SXS_GUID_INFORMATION_CLR +{ + DWORD cbSize; + DWORD dwFlags; + PCWSTR pcwszRuntimeVersion; + PCWSTR pcwszTypeName; + PCWSTR pcwszAssemblyIdentity; +} SXS_GUID_INFORMATION_CLR; + +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) 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; + + strcpy(path_file, path_tmp); + PathAppendA(path_file, 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 run_test(void) +{ + SIZE_T buffer_size; + BOOL ret; + SXS_GUID_INFORMATION_CLR *info; + WCHAR expected_type_name[] = {'D','L','L','.','T','e','s','t',0}; + WCHAR expected_runtime_version[] = {'v','4','.','0','.','0','.','0',0}; + WCHAR expected_assembly_identity[] = {'c','o','m','t','e','s','t',',','t','y','p','e','=','"','w','i','n','3','2','"',',','v','e','r','s','i','o','n','=','"','1','.','0','.','0','.','0','"',0}; + + ret = pSxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS, (GUID*)&CLSID_Test, NULL, NULL, 0, &buffer_size); + ok(ret == FALSE, "Got %d\n", ret); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got %d\n", GetLastError()); + + info = heap_alloc(buffer_size); + ret = pSxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS, (GUID*)&CLSID_Test, NULL, info, buffer_size, &buffer_size); + ok(ret == TRUE, "Got %d\n", ret); + ok(GetLastError() == 0, "Got %d\n", GetLastError()); + + ok(info->dwFlags == SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS, "Got %d\n", info->dwFlags); + ok(lstrcmpW(info->pcwszTypeName, expected_type_name) == 0, "Got %s\n", wine_dbgstr_w(info->pcwszTypeName)); + ok(lstrcmpW(info->pcwszAssemblyIdentity, expected_assembly_identity) == 0, "Got %s\n", wine_dbgstr_w(info->pcwszAssemblyIdentity)); + ok(lstrcmpW(info->pcwszRuntimeVersion, expected_runtime_version) == 0, "Got %s\n", wine_dbgstr_w(info->pcwszRuntimeVersion)); + + heap_free(info); +} + +static void prepare_and_run_test(void) +{ + char path_tmp[MAX_PATH] = {0}; + char path_manifest_dll[MAX_PATH] = {0}; + char path_manifest_exe[MAX_PATH] = {0}; + BOOL success; + ACTCTXA context = {0}; + ULONG_PTR cookie; + HANDLE handle_context = 0; + + GetTempPathA(MAX_PATH, path_tmp); + + if (!write_resource_file(path_tmp, "comtest_exe.manifest", "exe.manifest", path_manifest_exe)) + { + ok(0, "Failed to create file for testing\n"); + goto cleanup; + } + + if (!write_resource_file(path_tmp, "comtest_dll.manifest", "comtest.manifest", path_manifest_dll)) + { + ok(0, "Failed to create file for testing\n"); + goto cleanup; + } + + context.cbSize = sizeof(ACTCTXA); + context.lpSource = path_manifest_exe; + context.lpAssemblyDirectory = path_tmp; + context.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; + + handle_context = CreateActCtxA(&context); + ok(handle_context != NULL && handle_context != INVALID_HANDLE_VALUE, "CreateActCtxA failed: %d\n", GetLastError()); + + if (handle_context == NULL || handle_context == INVALID_HANDLE_VALUE) + { + ok(0, "Failed to create activation context\n"); + goto cleanup; + } + + success = ActivateActCtx(handle_context, &cookie); + ok(success, "ActivateActCtx failed: %d\n", GetLastError()); + + run_test(); + +cleanup: + if (handle_context != NULL && handle_context != INVALID_HANDLE_VALUE) + { + success = DeactivateActCtx(0, cookie); + ok(success, "DeactivateActCtx failed: %d\n", GetLastError()); + ReleaseActCtx(handle_context); + } + if (*path_manifest_exe) + { + success = DeleteFileA(path_manifest_exe); + ok(success, "DeleteFileA failed: %d\n", GetLastError()); + } + if(*path_manifest_dll) + { + success = DeleteFileA(path_manifest_dll); + ok(success, "DeleteFileA failed: %d\n", GetLastError()); + } +} + +static void run_child_process(void) +{ + 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 %s", argv[0], argv[1], "subtest"); + + 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); +} + +static void test_SxsLookupClrGuid(void) +{ + SIZE_T buffer_size; + BOOL ret; + + ret = pSxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS, (GUID*)&CLSID_Test, NULL, NULL, 0, &buffer_size); + ok(ret == FALSE, "Expected FALSE, got %d\n", ret); + ok(GetLastError() == ERROR_NOT_FOUND, "Expected ERROR_NOT_FOUND, got %d\n", GetLastError()); + + run_child_process(); +} + +START_TEST(sxs) +{ + int argc; + char **argv; + + pSxsLookupClrGuid = (void *)GetProcAddress(LoadLibraryA("sxs.dll"), "SxsLookupClrGuid"); + + argc = winetest_get_mainargs(&argv); + if (argc > 2) + { + prepare_and_run_test(); + return; + } + + test_SxsLookupClrGuid(); +}
It doesn't work here:
comtest.c:103: Test failed: Moving temporary file failed comtest: 1 failures in child process
I think it's trying to move the file in the temporary directory to itself.
It doesn't work here:
comtest.c:103: Test failed: Moving temporary file failed comtest: 1 failures in child process
I think it's trying to move the file in the temporary directory to itself.
It works on the testbot: https://testbot.winehq.org/JobDetails.pl?Key=43124 Moving a file to itself should generally work, too. Where is "here"? Can you tell me where it fails, so I can try to replicate and fix the issue?
Regards, Fabian Maurer
I'm using wine from master with your full patchset applied and wine-mono from master (built using the vagrant vm). I'm doing "make test" from the build tree. It appears to be run_type_current_working_directory that fails. On Sun, Oct 14, 2018 at 10:43 AM Fabian Maurer dark.shadow4@web.de wrote:
It doesn't work here:
comtest.c:103: Test failed: Moving temporary file failed
comtest: 1 failures in child process
I think it's trying to move the file in the temporary directory to itself.
It works on the testbot: https://testbot.winehq.org/JobDetails.pl?Key=43124
Moving a file to itself should generally work, too.
Where is "here"? Can you tell me where it fails, so I can try to replicate and fix the issue?
Regards,
Fabian Maurer
On Montag, 15. Oktober 2018 17:46:51 CET Vincent Povirk wrote:
I'm using wine from master with your full patchset applied and wine-mono from master (built using the vagrant vm). I'm doing "make test" from the build tree. It appears to be run_type_current_working_directory that fails.
Sorry for the late replay, this issue should be fixed since "7edfcd63ada3206b62f4fcee7b65d7a165a0cd9b kernel32: MoveFile(source, source) should succeed."
I'll resend the patches.
Regards, Fabian Maurer