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