PATCH: ITypelib::Invoke

Marcus Meissner marcus at jet.franken.de
Mon Jun 17 17:20:22 CDT 2002


Hi,

This generalises ITypeLib::Invoke somewhat, so that the MS COMCTL timepicker
now can be called from VBA.

Not 100% perfect, but better.

Ciao, Marcus

License: LGPL

Changelog:
	ITypelib::Invoke: Handle different length arguments better,
	we also return 1 VARIANT only.
	

Index: dlls/oleaut32/typelib.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/typelib.c,v
retrieving revision 1.72
diff -u -r1.72 typelib.c
--- dlls/oleaut32/typelib.c	10 Jun 2002 23:01:34 -0000	1.72
+++ dlls/oleaut32/typelib.c	17 Jun 2002 22:13:22 -0000
@@ -4087,6 +4087,8 @@
     return res;
 }
 
+extern int const _argsize(DWORD vt);
+
 static HRESULT WINAPI ITypeInfo_fnInvoke(
     ITypeInfo2 *iface,
     VOID  *pIUnk,
@@ -4114,35 +4116,62 @@
 	}
     if (pFDesc) {
 	dump_TLBFuncDescOne(pFDesc);
+	/* dump_FUNCDESC(&pFDesc->funcdesc);*/
 	switch (pFDesc->funcdesc.funckind) {
 	case FUNC_PUREVIRTUAL:
 	case FUNC_VIRTUAL: {
 	    DWORD res;
-	    DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
-	    DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
-	    args[0] = (DWORD)pIUnk;
+	    int   numargs, numargs2, argspos, args2pos;
+	    DWORD *args , *args2;
+
 
+	    numargs = 1; numargs2 = 0;
 	    for (i=0;i<pFDesc->funcdesc.cParams;i++) {
+		if (i<pDispParams->cArgs)
+		    numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
+		else {
+		    numargs	+= 1; /* sizeof(lpvoid) */
+		    numargs2	+= _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
+		}
+	    }
+
+	    args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
+	    args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
+
+	    args[0] = (DWORD)pIUnk;
+	    argspos = 1; args2pos = 0;
+	    for (i=0;i<pFDesc->funcdesc.cParams;i++) {
+		int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
 		if (i<pDispParams->cArgs) {
-		    TRACE("set %d to disparg type %d vs %d\n",i,
-			    V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
-			    pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
-		    );
-		    args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
+		    VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
+		    TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
+
+		    if (V_VT(arg) == tdesc->vt) {
+			memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
+		    } else {
+			if (tdesc->vt == 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),tdesc->vt
+			    );
+			}
+		    }
+		    argspos += arglen;
 		} else {
 		    TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
-		    TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
+		    FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
 		    /*FIXME: give pointers for the rest, so propertyget works*/
-		    args[i+1] = (DWORD)&args2[i];
+		    args[argspos] = (DWORD)&args2[args2pos];
 
-		    /* If pointer to variant, pass reference to variant
-		     * in result variant array.
-		     */
+		    /* If pointer to variant, pass reference it. */
 		    if ((tdesc->vt == VT_PTR) &&
 			(tdesc->u.lptdesc->vt == VT_VARIANT) &&
 			pVarResult
 		    )
-			args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
+			args[argspos]= (DWORD)pVarResult;
+		    argspos	+= 1;
+		    args2pos	+= arglen;
 		}
 	    }
 	    if (pFDesc->funcdesc.cParamsOpt)
@@ -4152,22 +4181,24 @@
 
 	    res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
 		    pFDesc->funcdesc.callconv,
-		    pFDesc->funcdesc.cParams+1,
+		    numargs,
 		    args
 	    );
 	    if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
+		args2pos = 0;
 		for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
+		    int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
 		    TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
 		    /* If we are a pointer to a variant, we are done already */
 		    if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
 			continue;
 
-		    VariantInit(&pVarResult[i]);
-		    V_UNION(pVarResult+i,intVal) = args2[i+pDispParams->cArgs];
+		    VariantInit(pVarResult);
+		    memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
 
 		    if (tdesc->vt == VT_PTR)
 			tdesc = tdesc->u.lptdesc;
-		    V_VT(pVarResult+i) = tdesc->vt;
+		    V_VT(pVarResult) = tdesc->vt;
 
 		    /* HACK: VB5 likes this.
 		     * I do not know why. There is 1 example in MSDN which uses
@@ -4175,9 +4206,10 @@
 		     * IDispatch*.).
 		     */
 		    if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
-			V_VT(pVarResult+i) = VT_DISPATCH;
-		    TRACE("storing into variant: [%d]\n", i);
-		    dump_Variant(pVarResult+i);
+			V_VT(pVarResult) = VT_DISPATCH;
+		    TRACE("storing into variant:\n");
+		    dump_Variant(pVarResult);
+		    args2pos += arglen;
 		}
 	    }
 	    HeapFree(GetProcessHeap(),0,args2);
Index: dlls/oleaut32/tmarshal.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/tmarshal.c,v
retrieving revision 1.7
diff -u -r1.7 tmarshal.c
--- dlls/oleaut32/tmarshal.c	14 Jun 2002 00:36:42 -0000	1.7
+++ dlls/oleaut32/tmarshal.c	17 Jun 2002 22:13:23 -0000
@@ -360,7 +360,7 @@
 };
 
 /* how much space do we use on stack in DWORD steps. */
-static int const
+int const
 _argsize(DWORD vt) {
     switch (vt) {
     case VT_DATE:



More information about the wine-patches mailing list