Zebediah Figura : rpcrt4: Properly handle complex arrays in the typelib marshaller.

Alexandre Julliard julliard at winehq.org
Tue Apr 2 16:09:58 CDT 2019


Module: wine
Branch: master
Commit: 3fd7a32a015923a5e153343cdc7b1d26ffb81c4e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=3fd7a32a015923a5e153343cdc7b1d26ffb81c4e

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Mon Apr  1 17:38:25 2019 -0500

rpcrt4: Properly handle complex arrays in the typelib marshaller.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/oleaut32/tests/tmarshal.c | 52 ++++++++++++++++++++++++------------------
 dlls/rpcrt4/ndr_typelib.c      | 33 +++++++++++++++++++--------
 2 files changed, 53 insertions(+), 32 deletions(-)

diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c
index 4f84442..ac0969b 100644
--- a/dlls/oleaut32/tests/tmarshal.c
+++ b/dlls/oleaut32/tests/tmarshal.c
@@ -1481,21 +1481,21 @@ static HRESULT WINAPI Widget_variant_array(IWidget *iface, VARIANT in[2], VARIAN
 {
     ok(V_VT(&in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in[0]));
     ok(V_I4(&in[0]) == 1, "Got wrong value %d.\n", V_I4(&in[0]));
-    ok(V_VT(&in[1]) == VT_I4, "Got wrong type %u.\n", V_VT(&in[1]));
-    ok(V_I4(&in[1]) == 2, "Got wrong value %d.\n", V_I4(&in[1]));
+    ok(V_VT(&in[1]) == (VT_BYREF|VT_I4), "Got wrong type %u.\n", V_VT(&in[1]));
+    ok(*V_I4REF(&in[1]) == 2, "Got wrong value %d.\n", *V_I4REF(&in[1]));
     ok(V_VT(&out[0]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[0]));
     ok(V_VT(&out[1]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[1]));
     ok(V_VT(&in_out[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in_out[0]));
     ok(V_I4(&in_out[0]) == 5, "Got wrong type %u.\n", V_VT(&in_out[0]));
-    ok(V_VT(&in_out[1]) == VT_I4, "Got wrong type %u.\n", V_VT(&in_out[1]));
-    ok(V_I4(&in_out[1]) == 6, "Got wrong type %u.\n", V_VT(&in_out[1]));
+    ok(V_VT(&in_out[1]) == VT_BSTR, "Got wrong type %u.\n", V_VT(&in_out[1]));
+    ok(!lstrcmpW(V_BSTR(&in_out[1]), test_bstr1), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&in[1])));
 
-    V_VT(&in[0]) = VT_I1;     V_I1(&in[0])     = 7;
-    V_VT(&in[1]) = VT_I1;     V_I1(&in[1])     = 8;
-    V_VT(&out[0]) = VT_I1;    V_I1(&out[0])    = 9;
-    V_VT(&out[1]) = VT_I1;    V_I1(&out[1])    = 10;
-    V_VT(&in_out[0]) = VT_I1; V_I1(&in_out[0]) = 11;
-    V_VT(&in_out[1]) = VT_I1; V_I1(&in_out[1]) = 12;
+    V_VT(&in[0]) = VT_I1;          V_I1(&in[0])          = 7;
+    V_VT(&in[1]) = VT_I1;          V_I1(&in[1])          = 8;
+    V_VT(&out[0]) = VT_I1;         V_I1(&out[0])         = 9;
+    V_VT(&out[1]) = VT_BSTR;       V_BSTR(&out[1])       = SysAllocString(test_bstr2);
+    V_VT(&in_out[0]) = VT_I1;      V_I1(&in_out[0])      = 11;
+    V_VT(&in_out[1]) = VT_UNKNOWN; V_UNKNOWN(&in_out[1]) = (IUnknown *)create_disp_obj();
 
     return S_OK;
 }
@@ -2581,9 +2581,11 @@ static void test_marshal_struct(IWidget *widget, IDispatch *disp)
 static void test_marshal_array(IWidget *widget, IDispatch *disp)
 {
     VARIANT var_in[2], var_out[2], var_in_out[2];
+    ISomethingFromDispatch *proxy_sfd;
     array_t in, out, in_out;
     MYSTRUCT struct_in[2];
     HRESULT hr;
+    int i = 2;
 
     memcpy(in, test_array1, sizeof(array_t));
     memcpy(out, test_array2, sizeof(array_t));
@@ -2594,26 +2596,32 @@ static void test_marshal_array(IWidget *widget, IDispatch *disp)
     ok(!memcmp(&out, &test_array5, sizeof(array_t)), "Arrays didn't match.\n");
     ok(!memcmp(&in_out, &test_array6, sizeof(array_t)), "Arrays didn't match.\n");
 
-    V_VT(&var_in[0]) = VT_I4;     V_I4(&var_in[0])     = 1;
-    V_VT(&var_in[1]) = VT_I4;     V_I4(&var_in[1])     = 2;
-    V_VT(&var_out[0]) = VT_I4;    V_I4(&var_out[0])    = 3;
-    V_VT(&var_out[1]) = VT_I4;    V_I4(&var_out[1])    = 4;
-    V_VT(&var_in_out[0]) = VT_I4; V_I4(&var_in_out[0]) = 5;
-    V_VT(&var_in_out[1]) = VT_I4; V_I4(&var_in_out[1]) = 6;
+    V_VT(&var_in[0]) = VT_I4;          V_I4(&var_in[0])       = 1;
+    V_VT(&var_in[1]) = VT_BYREF|VT_I4; V_I4REF(&var_in[1])    = &i;
+    V_VT(&var_out[0]) = VT_I4;         V_I4(&var_out[0])      = 3;
+    V_VT(&var_out[1]) = VT_I4;         V_I4(&var_out[1])      = 4;
+    V_VT(&var_in_out[0]) = VT_I4;      V_I4(&var_in_out[0])   = 5;
+    V_VT(&var_in_out[1]) = VT_BSTR;    V_BSTR(&var_in_out[1]) = SysAllocString(test_bstr1);
     hr = IWidget_variant_array(widget, var_in, var_out, var_in_out);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
     ok(V_VT(&var_in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&var_in[0]));
     ok(V_I4(&var_in[0]) == 1, "Got wrong value %d.\n", V_I4(&var_in[0]));
-    ok(V_VT(&var_in[1]) == VT_I4, "Got wrong type %u.\n", V_VT(&var_in[1]));
-    ok(V_I4(&var_in[1]) == 2, "Got wrong value %d.\n", V_I4(&var_in[1]));
+    ok(V_VT(&var_in[1]) == (VT_BYREF|VT_I4), "Got wrong type %u.\n", V_VT(&var_in[1]));
+    ok(V_I4REF(&var_in[1]) == &i, "Got wrong value %p.\n", V_I4REF(&var_in[1]));
+    ok(i == 2, "Got wrong value %d.\n", i);
     ok(V_VT(&var_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_out[0]));
     ok(V_I1(&var_out[0]) == 9, "Got wrong value %u.\n", V_VT(&var_out[0]));
-    ok(V_VT(&var_out[1]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_out[1]));
-    ok(V_I1(&var_out[1]) == 10, "Got wrong value %u.\n", V_VT(&var_out[1]));
+    ok(V_VT(&var_out[1]) == VT_BSTR, "Got wrong type %u.\n", V_VT(&var_out[1]));
+    ok(!lstrcmpW(V_BSTR(&var_out[1]), test_bstr2), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&var_out[1])));
     ok(V_VT(&var_in_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_in_out[0]));
     ok(V_I1(&var_in_out[0]) == 11, "Got wrong value %u.\n", V_VT(&var_in_out[0]));
-    ok(V_VT(&var_in_out[1]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_in_out[1]));
-    ok(V_I1(&var_in_out[1]) == 12, "Got wrong value %u.\n", V_VT(&var_in_out[1]));
+    ok(V_VT(&var_in_out[1]) == VT_UNKNOWN, "Got wrong type %u.\n", V_VT(&var_in_out[1]));
+    hr = IUnknown_QueryInterface(V_UNKNOWN(&var_in_out[1]), &IID_ISomethingFromDispatch, (void **)&proxy_sfd);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = ISomethingFromDispatch_anotherfn(proxy_sfd);
+    ok(hr == 0x01234567, "Got hr %#x.\n", hr);
+    ISomethingFromDispatch_Release(proxy_sfd);
+    release_iface(V_UNKNOWN(&var_in_out[1]));
 
     memcpy(&struct_in[0], &test_mystruct1, sizeof(MYSTRUCT));
     memcpy(&struct_in[1], &test_mystruct2, sizeof(MYSTRUCT));
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c
index 5a4de51..5c48010 100644
--- a/dlls/rpcrt4/ndr_typelib.c
+++ b/dlls/rpcrt4/ndr_typelib.c
@@ -326,9 +326,13 @@ static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr)
 
 static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc)
 {
-    if (get_basetype(typeinfo, desc))
+    switch (desc->vt)
+    {
+    case VT_CY:
         return FC_LGFARRAY;
-    else if (desc->vt == VT_USERDEFINED)
+    case VT_CARRAY:
+        return get_array_fc(typeinfo, &desc->lpadesc->tdescElem);
+    case VT_USERDEFINED:
     {
         ITypeInfo *refinfo;
         TYPEATTR *attr;
@@ -351,8 +355,9 @@ static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc)
 
         return fc;
     }
-    else
-        return FC_BOGUS_ARRAY;
+    default:
+        return get_basetype(typeinfo, desc) ? FC_LGFARRAY : FC_BOGUS_ARRAY;
+    }
 }
 
 static BOOL type_is_non_iface_pointer(ITypeInfo *typeinfo, TYPEDESC *desc)
@@ -616,14 +621,11 @@ static size_t write_array_tfs(ITypeInfo *typeinfo, unsigned char *str,
     size_t *len, ARRAYDESC *desc)
 {
     unsigned char fc = get_array_fc(typeinfo, &desc->tdescElem);
-    ULONG size = type_memsize(typeinfo, &desc->tdescElem);
     unsigned char basetype;
     size_t ref = 0, off;
+    ULONG size = 1;
     USHORT i;
 
-    if (fc != FC_LGFARRAY)
-        FIXME("complex arrays not implemented\n");
-
     if (!(basetype = get_basetype(typeinfo, &desc->tdescElem)))
         ref = write_type_tfs(typeinfo, str, len, &desc->tdescElem, FALSE, FALSE);
 
@@ -633,9 +635,20 @@ static size_t write_array_tfs(ITypeInfo *typeinfo, unsigned char *str,
 
     off = *len;
 
-    WRITE_CHAR(str, *len, FC_LGFARRAY);
+    WRITE_CHAR(str, *len, fc);
     WRITE_CHAR(str, *len, 0);
-    WRITE_INT (str, *len, size);
+    if (fc == FC_BOGUS_ARRAY)
+    {
+        WRITE_SHORT(str, *len, size);
+        WRITE_INT(str, *len, 0xffffffff); /* conformance */
+        WRITE_INT(str, *len, 0xffffffff); /* variance */
+    }
+    else
+    {
+        size *= type_memsize(typeinfo, &desc->tdescElem);
+        WRITE_INT(str, *len, size);
+    }
+
     if (basetype)
         WRITE_CHAR(str, *len, basetype);
     else




More information about the wine-cvs mailing list