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: