[PATCH 3/6] mscoree: Allow loading of registration free .NET COM objects
Fabian Maurer
dark.shadow4 at web.de
Tue Aug 7 12:45:09 CDT 2018
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43270
Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
dlls/mscoree/corruntimehost.c | 218 ++++++++++++++++++++++++----------
dlls/mscoree/tests/comtest.c | 2 -
2 files changed, 157 insertions(+), 63 deletions(-)
diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c
index 0c933cac29..cd9c1c3234 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 );
@@ -1606,6 +1608,93 @@ HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid,
return CLASS_E_CLASSNOTAVAILABLE;
}
+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 BOOL try_create_registration_free_com(REFIID clsid, WCHAR *classname, WCHAR *filename)
+{
+ 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);
+
+ GetCurrentDirectoryW(MAX_PATH, 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 +1729,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 = sizeof(subkeyName) / sizeof(WCHAR);
+ 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 = sizeof(subkeyName) / sizeof(WCHAR);
- 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))
+ 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 63e43f4b95..a73a7fc5fc 100644
--- a/dlls/mscoree/tests/comtest.c
+++ b/dlls/mscoree/tests/comtest.c
@@ -70,7 +70,6 @@ static void run_test(int run)
IClassFactory *classFactory = NULL;
hr = CoCreateInstance(&CLSID_Test, NULL, CLSCTX_INPROC_SERVER, &IID_ITest, (void**)&test);
- todo_wine
ok(hr == S_OK, "Got %x\n", hr);
if (test)
@@ -89,7 +88,6 @@ static void run_test(int run)
{
ITest *test2 = NULL;
hr = IClassFactory_CreateInstance(classFactory, NULL, &IID_ITest, (void **)&test2);
- todo_wine
ok(hr == S_OK, "Got %x\n", hr);
if (test2)
--
2.18.0
More information about the wine-devel
mailing list