OleAut32: improved DispCallFunc implementation

Alberto Massari alby at exln.com
Wed Dec 11 14:41:37 CST 2002


Changelog:
 - calling SafeArrayDestroy on a destroyed array should be a no-op
 - implemented DispCallFunc so that it works when calling event handlers that 
   have no return value.

Alberto

Index: safearray.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/safearray.c,v
retrieving revision 1.19
diff -u -r1.19 safearray.c
--- safearray.c	5 Dec 2002 20:33:08 -0000	1.19
+++ safearray.c	11 Dec 2002 20:12:34 -0000
@@ -578,6 +578,9 @@
   if(psa->cLocks > 0)
     return DISP_E_ARRAYISLOCKED;
 
+  if(psa->pvData==NULL)
+    return S_OK;
+
   ulWholeArraySize = getArraySize(psa);
 
   if(isPointer(psa->fFeatures)) {           /* release the pointers */
Index: typelib.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/typelib.c,v
retrieving revision 1.82
diff -u -r1.82 typelib.c
--- typelib.c	5 Dec 2002 20:33:08 -0000	1.82
+++ typelib.c	11 Dec 2002 20:23:10 -0000
@@ -4204,39 +4204,53 @@
     DWORD *args;
     HRESULT hres;
 
-    FIXME("(%p, %ld, %d, %d, %d, %p, %p, %p)\n",
-	pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult
+    TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
+	pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
     );
-    argsize = 0;
+    /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
+    So we need to add a first parameter to the list of arguments, to supply the interface pointer */
+    argsize = 1;
     for (i=0;i<cActuals;i++) {
-        FIXME("arg %d: type %d\n",i,prgvt[i]);
+        TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
 	dump_Variant(prgpvarg[i]);
         argsize += _argsize(prgvt[i]);
     }
     args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
-    argspos = 0;
+    args[0]=0;      /* this is the fake IDispatch interface pointer */
+    argspos = 1;
     for (i=0;i<cActuals;i++) {
 	int arglen;
         VARIANT *arg = prgpvarg[i];
-
+        TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
 	arglen = _argsize(prgvt[i]);
 	if (V_VT(arg) == prgvt[i]) {
 	    memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
+	} else if (prgvt[i] == VT_VARIANT) {
+	    memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
+    } else if (prgvt[i]==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
+        /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct;
+        so, don't invoke VariantChangeType */
+        memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
+	} else if (VariantChangeType(arg,arg,0,prgvt[i])==S_OK) {
+        FIXME("argument was coerced in-place; source data has been modified!!!\n");
+	    memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
 	} else {
-	    if (prgvt[i] == VT_VARIANT) {
-		memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
-	    } else {
-		ERR("Set arg %d to disparg type %d vs %d\n",i,
-			V_VT(arg),prgvt[i]
-		);
-	    }
+	    ERR("Set arg %d to disparg type %d vs %d\n",i,V_VT(arg),prgvt[i]);
 	}
 	argspos += arglen;
     }
 
-    FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
-
-    hres = _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize/4,args);
+    if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
+    {
+        _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize,args);
+        hres=S_OK;
+    }
+    else
+    {
+        FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
+        hres = _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize,args);
+        FIXME("Method returned %lx\n",hres);
+    }
     HeapFree(GetProcessHeap(),0,args);
     return hres;
 }





More information about the wine-patches mailing list