[PATCH 1/2] oleaut32: Implement LPSAFEARRAY user marshal interface marshaling.

Connor McAdams cmcadams at codeweavers.com
Tue Nov 23 13:16:19 CST 2021


Signed-off-by: Connor McAdams <cmcadams at codeweavers.com>
---
 dlls/oleaut32/usrmarshal.c | 84 ++++++++++++++++++++++++++++++++++----
 1 file changed, 75 insertions(+), 9 deletions(-)

diff --git a/dlls/oleaut32/usrmarshal.c b/dlls/oleaut32/usrmarshal.c
index 5eeafb8e378..69c7c1cfdda 100644
--- a/dlls/oleaut32/usrmarshal.c
+++ b/dlls/oleaut32/usrmarshal.c
@@ -286,6 +286,12 @@ static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, IUnknown *pun
     return size;
 }
 
+static ULONG interface_safearray_size(ULONG *pFlags, ULONG Start, REFIID riid, IUnknown *punk)
+{
+    TRACE("(%x,%d,%p)\n", *pFlags, Start, punk);
+    return Start + interface_variant_size(pFlags, riid, punk);
+}
+
 static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
 {
   if (V_ISARRAY(pvar))
@@ -733,22 +739,40 @@ static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa)
 
 static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
 {
-    if (sftype == SF_BSTR)
+    switch (sftype)
+    {
+    case SF_BSTR:
+    case SF_HAVEIID:
+    case SF_UNKNOWN:
+    case SF_DISPATCH:
         return sizeof(DWORD);
-    else if (sftype == SF_VARIANT)
+
+    case SF_VARIANT:
         return sizeof(variant_wire_t) - sizeof(DWORD);
-    else
+
+    default:
         return lpsa->cbElements;
+    }
 }
 
 static DWORD elem_mem_size(wireSAFEARRAY wiresa, SF_TYPE sftype)
 {
-    if (sftype == SF_BSTR)
+    switch (sftype)
+    {
+    case SF_HAVEIID:
+    case SF_UNKNOWN:
+    case SF_DISPATCH:
+        return sizeof(void *);
+
+    case SF_BSTR:
         return sizeof(BSTR);
-    else if (sftype == SF_VARIANT)
+
+    case SF_VARIANT:
         return sizeof(VARIANT);
-    else
+
+    default:
         return wiresa->cbElements;
+    }
 }
 
 ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa)
@@ -795,6 +819,22 @@ ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY
             case SF_DISPATCH:
             case SF_UNKNOWN:
             case SF_HAVEIID:
+            {
+                IUnknown **lpUnk;
+                GUID guid;
+
+                if (sftype == SF_HAVEIID)
+                    SafeArrayGetIID(psa, &guid);
+                else if (sftype == SF_UNKNOWN)
+                    memcpy(&guid, &IID_IUnknown, sizeof(guid));
+                else
+                    memcpy(&guid, &IID_IDispatch, sizeof(guid));
+
+                for (lpUnk = psa->pvData; ulCellCount; ulCellCount--, lpUnk++)
+                    size = interface_safearray_size(pFlags, size, &guid, *lpUnk);
+
+                break;
+            }
                 FIXME("size interfaces\n");
                 break;
             case SF_VARIANT:
@@ -870,7 +910,7 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf
         Buffer += sizeof(ULONG);
 
         hr = SafeArrayGetVartype(psa, &vt);
-        if (FAILED(hr)) vt = 0;
+        if ((psa->fFeatures & FADF_HAVEIID) || FAILED(hr)) vt = 0;
 
         *(ULONG *)Buffer = (USHORT)psa->cLocks | (vt << 16);
         Buffer += sizeof(ULONG);
@@ -916,8 +956,21 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf
                 case SF_DISPATCH:
                 case SF_UNKNOWN:
                 case SF_HAVEIID:
-                    FIXME("marshal interfaces\n");
+                {
+                    IUnknown **lpUnk;
+
+                    for (lpUnk = psa->pvData; ulCellCount; ulCellCount--, lpUnk++)
+                    {
+                        if (sftype == SF_HAVEIID)
+                            Buffer = interface_variant_marshal(pFlags, Buffer, &guid, *lpUnk);
+                        else if (sftype == SF_UNKNOWN)
+                            Buffer = interface_variant_marshal(pFlags, Buffer, &IID_IUnknown, *lpUnk);
+                        else
+                            Buffer = interface_variant_marshal(pFlags, Buffer, &IID_IDispatch, *lpUnk);
+                    }
+
                     break;
+                }
                 case SF_VARIANT:
                 {
                     VARIANT* lpVariant;
@@ -1093,8 +1146,21 @@ unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *B
             case SF_DISPATCH:
             case SF_UNKNOWN:
             case SF_HAVEIID:
-                FIXME("marshal interfaces\n");
+            {
+                IUnknown **lpUnk;
+
+                for (lpUnk = (*ppsa)->pvData; cell_count; cell_count--, lpUnk++)
+                {
+                    if (sftype == SF_HAVEIID)
+                        Buffer = interface_variant_unmarshal(pFlags, Buffer, &guid, lpUnk);
+                    else if (sftype == SF_UNKNOWN)
+                        Buffer = interface_variant_unmarshal(pFlags, Buffer, &IID_IUnknown, lpUnk);
+                    else
+                        Buffer = interface_variant_unmarshal(pFlags, Buffer, &IID_IDispatch, lpUnk);
+                }
+
                 break;
+            }
             case SF_VARIANT:
             {
                 VARIANT* lpVariant;
-- 
2.25.1




More information about the wine-devel mailing list