[PATCH 2/3] sxs: Implement surrogate data lookup in SxsLookupClrGuid().

Nikolay Sivov nsivov at codeweavers.com
Tue Jul 21 07:03:28 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/sxs/sxs.c                      | 80 ++++++++++++++++++++++-------
 dlls/sxs/tests/comtest_dll.manifest |  5 ++
 dlls/sxs/tests/interfaces.idl       |  5 ++
 dlls/sxs/tests/sxs.c                | 33 ++++++++++++
 4 files changed, 104 insertions(+), 19 deletions(-)

diff --git a/dlls/sxs/sxs.c b/dlls/sxs/sxs.c
index 0b59eb5d2e9..92ba18ab0ea 100644
--- a/dlls/sxs/sxs.c
+++ b/dlls/sxs/sxs.c
@@ -60,6 +60,7 @@ typedef struct _SXS_GUID_INFORMATION_CLR
 #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)
 
 struct comclassredirect_data
 {
@@ -96,27 +97,54 @@ struct clrclass_data
     DWORD res2[2];
 };
 
+struct clrsurrogate_data
+{
+    ULONG size;
+    DWORD res;
+    GUID  clsid;
+    ULONG version_offset;
+    ULONG version_len;
+    ULONG name_offset;
+    ULONG name_len;
+};
+
 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;
+    unsigned int len_version = 0, len_name, len_identity;
     const void *ptr_name, *ptr_version, *ptr_identity;
     SXS_GUID_INFORMATION_CLR *ret = buffer;
+    BOOL retval = FALSE;
     char *ret_strings;
 
-    TRACE("(%x, %s, %p, %p, %08lx, %p): stub\n", flags, wine_dbgstr_guid(clsid), actctx,
+    TRACE("%#x, %s, %p, %p, %lx, %p.\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 (flags & ~SXS_LOOKUP_CLR_GUID_FIND_ANY)
+        FIXME("Ignored flags: %x\n", flags & ~SXS_LOOKUP_CLR_GUID_FIND_ANY);
 
-    if (!FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, 0,
-                               ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, clsid, &guid_info))
+    if (flags & SXS_LOOKUP_CLR_GUID_FIND_SURROGATE)
+    {
+        if ((retval = FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, 0,
+                ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES, clsid, &guid_info)))
+        {
+            flags &= ~SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS;
+        }
+    }
+
+    if (!retval && (flags & SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS))
+    {
+        if ((retval = FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, 0,
+                ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, clsid, &guid_info)))
+        {
+            flags &= ~SXS_LOOKUP_CLR_GUID_FIND_SURROGATE;
+        }
+    }
+
+    if (!retval)
     {
         SetLastError(ERROR_NOT_FOUND);
         return FALSE;
@@ -139,17 +167,30 @@ BOOL WINAPI SxsLookupClrGuid(DWORD flags, GUID *clsid, HANDLE actctx, void *buff
         return FALSE;
     }
 
-    redirect_data = guid_info.lpData;
-    class_data = (void *)((char*)redirect_data + redirect_data->clrdata_offset);
+    if (flags & SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS)
+    {
+        const struct comclassredirect_data *redirect_data = guid_info.lpData;
+        const struct clrclass_data *class_data;
+
+        class_data = (void *)((char *)redirect_data + redirect_data->clrdata_offset);
+        ptr_name = (char *)class_data + class_data->name_offset;
+        ptr_version = (char *)class_data + class_data->version_offset;
+        len_name = class_data->name_len + sizeof(WCHAR);
+        if (class_data->version_len)
+            len_version = class_data->version_len + sizeof(WCHAR);
+    }
+    else
+    {
+        const struct clrsurrogate_data *surrogate = guid_info.lpData;
+        ptr_name = (char *)surrogate + surrogate->name_offset;
+        ptr_version = (char *)surrogate + surrogate->version_offset;
+        len_name = surrogate->name_len + sizeof(WCHAR);
+        if (surrogate->version_len)
+            len_version = surrogate->version_len + sizeof(WCHAR);
+    }
 
     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)
@@ -160,11 +201,12 @@ BOOL WINAPI SxsLookupClrGuid(DWORD flags, GUID *clsid, HANDLE actctx, void *buff
         return FALSE;
     }
 
-    ret->cbSize = sizeof(SXS_GUID_INFORMATION_CLR);
-    ret->dwFlags = SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS;
+    ret->cbSize = sizeof(*ret);
+    ret->dwFlags = flags & SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS ? SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS :
+            SXS_GUID_INFORMATION_CLR_FLAG_IS_SURROGATE;
 
     /* Copy strings into buffer */
-    ret_strings = (char *)ret + sizeof(SXS_GUID_INFORMATION_CLR);
+    ret_strings = (char *)ret + sizeof(*ret);
 
     memcpy(ret_strings, ptr_identity, len_identity);
     ret->pcwszAssemblyIdentity = (WCHAR *)ret_strings;
diff --git a/dlls/sxs/tests/comtest_dll.manifest b/dlls/sxs/tests/comtest_dll.manifest
index ef6924de9e8..b3273457edf 100644
--- a/dlls/sxs/tests/comtest_dll.manifest
+++ b/dlls/sxs/tests/comtest_dll.manifest
@@ -11,6 +11,11 @@
         name="DLL.Test"
         runtimeVersion="v4.0.0.0">
     </clrClass>
+    <clrSurrogate
+        clsid="{2e106e50-e7a4-4489-8538-83643f100fdd}"
+        name="Surrogate.Test"
+        runtimeVersion="v4.0.0.1">
+    </clrSurrogate>
     <file name="comtest.dll">
     </file>
 </assembly>
diff --git a/dlls/sxs/tests/interfaces.idl b/dlls/sxs/tests/interfaces.idl
index 6f8ac615bf2..f34660db75c 100644
--- a/dlls/sxs/tests/interfaces.idl
+++ b/dlls/sxs/tests/interfaces.idl
@@ -33,3 +33,8 @@ interface ITest : IUnknown {
     uuid(2e106e50-e7a4-4489-8538-83643f100fdc),
 ]
 coclass Test { interface ITest; };
+
+[
+    uuid(2e106e50-e7a4-4489-8538-83643f100fdd),
+]
+coclass SurrogateTest { interface ITest; };
diff --git a/dlls/sxs/tests/sxs.c b/dlls/sxs/tests/sxs.c
index 4215c5045bd..9887871422a 100644
--- a/dlls/sxs/tests/sxs.c
+++ b/dlls/sxs/tests/sxs.c
@@ -86,6 +86,10 @@ static void run_test(void)
     BOOL ret;
     SXS_GUID_INFORMATION_CLR *info;
 
+    ret = SxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_ANY, (GUID*)&CLSID_Test, NULL, NULL, 0, &buffer_size);
+    ok(!ret, "Unexpected return value %d.\n", ret);
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got %d\n", GetLastError());
+
     ret = SxsLookupClrGuid(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());
@@ -103,6 +107,29 @@ static void run_test(void)
            wine_dbgstr_w(info->pcwszRuntimeVersion));
 
     heap_free(info);
+
+    ret = SxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_SURROGATE, (GUID *)&CLSID_SurrogateTest, NULL, NULL, 0, &buffer_size);
+    ok(!ret, "Unexpected return value %d.\n", ret);
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got %d\n", GetLastError());
+
+    info = heap_alloc(buffer_size);
+    ret = SxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_SURROGATE, (GUID *)&CLSID_SurrogateTest, NULL, info,
+            buffer_size, &buffer_size);
+    ok(ret, "Unexpected return value %d.\n", ret);
+    ok(GetLastError() == 0, "Got %d\n", GetLastError());
+
+    ok(info->dwFlags == SXS_GUID_INFORMATION_CLR_FLAG_IS_SURROGATE, "Unexpected flags %#x.\n", info->dwFlags);
+    ok(!lstrcmpW(info->pcwszTypeName, L"Surrogate.Test"), "Unexpected typename %s.\n", wine_dbgstr_w(info->pcwszTypeName));
+    ok(!lstrcmpW(info->pcwszAssemblyIdentity, L"comtest,type=\"win32\",version=\"1.0.0.0\""),
+           "Unexpected assembly identity %s.\n", wine_dbgstr_w(info->pcwszAssemblyIdentity));
+    ok(!lstrcmpW(info->pcwszRuntimeVersion, L"v4.0.0.1"), "Unexpected runtime version %s.\n",
+           wine_dbgstr_w(info->pcwszRuntimeVersion));
+
+    heap_free(info);
+
+    ret = SxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_ANY, (GUID *)&CLSID_SurrogateTest, NULL, NULL, 0, &buffer_size);
+    ok(!ret, "Unexpected return value %d.\n", ret);
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got %d\n", GetLastError());
 }
 
 static void prepare_and_run_test(void)
@@ -199,10 +226,16 @@ static void test_SxsLookupClrGuid(void)
     SIZE_T buffer_size;
     BOOL ret;
 
+    SetLastError(0xdeadbeef);
     ret = SxsLookupClrGuid(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());
 
+    SetLastError(0xdeadbeef);
+    ret = SxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_SURROGATE, (GUID *)&CLSID_Test, NULL, NULL, 0, &buffer_size);
+    ok(!ret, "Unexpected return value %d.\n", ret);
+    ok(GetLastError() == ERROR_NOT_FOUND, "Expected ERROR_NOT_FOUND, got %d\n", GetLastError());
+
     run_child_process();
 }
 
-- 
2.27.0




More information about the wine-devel mailing list