Hi, This obsoletes parts of the VB6 rollup patch I posted some days ago. Ciao, Marcus Changelog: Process TKIND_ALIAS in SLTG typelibs, 0x14 in the tail is the tdescAlias.vt entry. Added a small handler for TKIND_DISPATCH in SLTG. ITypeLib_Release can have a NULL pointer as ITypeInfo*. Split out _copy_arg function for both DispCall and ITypeInfo_fnInvoke, added some more functionality. ITypeInfo_fnInvoke can handle VT_USERDEFINED variants. Index: typelib.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/typelib.c,v retrieving revision 1.84 diff -u -r1.84 typelib.c --- typelib.c 12 Dec 2002 22:59:25 -0000 1.84 +++ typelib.c 28 Dec 2002 20:48:02 -0000 @@ -573,9 +573,6 @@ return S_OK; /* FIXME: pretend everything is OK */ } -/* for better debugging info leave the static out for the time being */ -#define static - /*======================= ITypeLib implementation =======================*/ typedef struct tagTLBCustData @@ -1030,7 +1025,13 @@ TRACE("%d\n", *(short*)ref); break; + case VT_UI4: + case VT_UINT: + TRACE("%u\n", *(UINT*)ref); + break; + case VT_I4: + case VT_INT: TRACE("%d\n", *(INT*)ref); break; @@ -2727,6 +2734,58 @@ return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra); } +static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI, + char *pNameTable) +{ + SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk; + SLTG_MemberHeader *pMemHeader; + SLTG_AliasItem *pItem; + int i, mustbelast; + + pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table); + pItem = (SLTG_AliasItem*)(pMemHeader + 1); + + mustbelast = 0; + /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */ + for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) { + if (pItem->vt == 0xffff) { + if (i<(pMemHeader->cbExtra/4-1)) + FIXME("Endmarker too early in process alias data!\n"); + break; + } + if (mustbelast) { + FIXME("Chain extends over last entry?\n"); + break; + } + if (pItem->vt == VT_USERDEFINED) { + pTI->TypeAttr.tdescAlias.vt = pItem->vt; + /* guessing here ... */ + FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02); + pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02; + mustbelast = 1; + } else { + FIXME("alias %d: 0x%x\n",i,pItem->vt); + FIXME("alias %d: 0x%x\n",i,pItem->res02); + } + pItem++; + } + return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra); +} + +static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI, + char *pNameTable) +{ + SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk; + SLTG_MemberHeader *pMemHeader; + SLTG_AliasItem *pItem; + + pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table); + pItem = (SLTG_AliasItem*)(pMemHeader + 1); + FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra); + FIXME("offset 0 0x%x\n",*(WORD*)pItem); + return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra); +} + static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI, char *pNameTable) { @@ -3016,6 +3075,16 @@ pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable); break; + case TKIND_ALIAS: + pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable); + if (pTITail->tdescalias_vt) + (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt; + break; + + case TKIND_DISPATCH: + pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable); + break; + default: FIXME("Not processing typekind %d\n", pTIHeader->typekind); pTITail = NULL; @@ -3028,6 +3097,28 @@ (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment; (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance; (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft; + +#define X(x) TRACE("tt "#x": %x\n",pTITail->res##x); + X(06); + X(08); + X(0a); + X(0c); + X(0e); + X(10); + X(12); + X(16); + X(18); + X(1a); + X(1c); + X(1e); + X(24); + X(26); + X(2a); + X(2c); + X(2e); + X(30); + X(32); + X(34); } ppTypeInfoImpl = &((*ppTypeInfoImpl)->next); pBlk = (char*)pBlk + pBlkEntry[order].len; @@ -3122,7 +3213,8 @@ This->HelpStringDll = NULL; } - ITypeInfo_Release((ITypeInfo*) This->pTypeInfo); + if (This->pTypeInfo) /* can be NULL */ + ITypeInfo_Release((ITypeInfo*) This->pTypeInfo); HeapFree(GetProcessHeap(),0,This); return 0; } @@ -3885,7 +3977,7 @@ TLBImplType *pImpl = This->impltypelist; TRACE("(%p) index %d\n", This, index); - dump_TypeInfo(This); + if (TRACE_ON(ole)) dump_TypeInfo(This); if(index==(UINT)-1) { @@ -4089,6 +4181,89 @@ extern int const _argsize(DWORD vt); +/**************************************************************************** + * Helper functions for Dispcall / Invoke, which copies one variant + * with target type onto the argument stack. + */ +static HRESULT +_copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc, + DWORD *argpos, VARIANT *arg, VARTYPE vt +) { + UINT arglen = _argsize(vt)*sizeof(DWORD); + VARTYPE oldvt; + + if (V_VT(arg) == vt) { + memcpy(argpos, &V_UNION(arg,lVal), arglen); + return S_OK; + } + + if (vt == VT_VARIANT) { + memcpy(argpos, arg, arglen); + return S_OK; + } + /* Deref BYREF vars if there is need */ + if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) { + memcpy(argpos,(void*)V_UNION(arg,lVal), arglen); + return S_OK; + } + if (vt==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(argpos,&V_UNION(arg,lVal), arglen); + return S_OK; + } + if ((vt == VT_PTR) && tdesc) + return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt); + if ((vt == VT_USERDEFINED) && tdesc && tinfo) { + ITypeInfo *tinfo2; + TYPEATTR *tattr; + HRESULT hres; + + hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); + if (hres) { + FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing from vt 0x%x. Copying 4 byte.\n",tdesc->u.hreftype,V_VT(arg)); + memcpy(argpos, &V_UNION(arg,lVal), 4); + return S_OK; + } + ITypeInfo_GetTypeAttr(tinfo2,&tattr); + switch (tattr->typekind) { + case TKIND_ENUM: + if (V_VT(arg) == VT_I4) { + memcpy(argpos, &V_UNION(arg,iVal), 4); + return S_OK; + } + FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg)); + break; + case TKIND_ALIAS: + tdesc = &(tattr->tdescAlias); + hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt); + ITypeInfo_Release(tinfo2); + return hres; + + case TKIND_INTERFACE: + FIXME("TKIND_INTERFACE unhandled.\n"); + break; + case TKIND_DISPATCH: + FIXME("TKIND_DISPATCH unhandled.\n"); + break; + case TKIND_RECORD: + FIXME("TKIND_RECORD unhandled.\n"); + break; + default: + FIXME("TKIND %d unhandled.\n",tattr->typekind); + break; + } + return E_FAIL; + } + oldvt = V_VT(arg); + if (VariantChangeType(arg,arg,0,vt)==S_OK) { + FIXME("argument was coerced in-place (0x%x -> 0x%x); source data has been modified!!!\n", oldvt, vt); + memcpy(argpos,&V_UNION(arg,lVal), arglen); + return S_OK; + } + ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt); + return E_FAIL; +} + /*********************************************************************** * DispCallFunc (OLEAUT32.@) */ @@ -4108,33 +4283,18 @@ 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++) { - TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i])); + TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i])); dump_Variant(prgpvarg[i]); - argsize += _argsize(prgvt[i]); + argsize += _argsize(prgvt[i]); } args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize); - args[0]=0; /* this is the fake IDispatch interface pointer */ + args[0] = (DWORD)pvInstance; /* 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 { - ERR("Set arg %d to disparg type %d vs %d\n",i,V_VT(arg),prgvt[i]); - } - argspos += arglen; + VARIANT *arg = prgpvarg[i]; + TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]); + _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]); + argspos += _argsize(prgvt[i]); } if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY) @@ -4166,6 +4326,7 @@ TLBFuncDesc * pFDesc; TLBVarDesc * pVDesc; int i; + HRESULT hres; TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n", This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr @@ -4178,7 +4339,7 @@ break; } if (pFDesc) { - dump_TLBFuncDescOne(pFDesc); + if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc); /* dump_FUNCDESC(&pFDesc->funcdesc);*/ switch (pFDesc->funcdesc.funckind) { case FUNC_PUREVIRTUAL: @@ -4208,18 +4369,8 @@ if (i<pDispParams->cArgs) { 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(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==tdesc->vt)) { - memcpy(&args[argspos],(void*)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 - ); - } + hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt); + if (FAILED(hres)) return hres; argspos += arglen; } else { TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc); @@ -4262,6 +4413,40 @@ if (tdesc->vt == VT_PTR) tdesc = tdesc->u.lptdesc; + if (tdesc->vt == VT_USERDEFINED) { + ITypeInfo *tinfo2; + TYPEATTR *tattr; + + hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2); + if (hres) { + FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype); + return E_FAIL; + } + ITypeInfo_GetTypeAttr(tinfo2,&tattr); + switch (tattr->typekind) { + case TKIND_ENUM: + FIXME("TKIND_ENUM unhandled.\n"); + break; + case TKIND_ALIAS: + TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt); + tdesc = &(tattr->tdescAlias); + break; + + case TKIND_INTERFACE: + FIXME("TKIND_INTERFACE unhandled.\n"); + break; + case TKIND_DISPATCH: + FIXME("TKIND_DISPATCH unhandled.\n"); + break; + case TKIND_RECORD: + FIXME("TKIND_RECORD unhandled.\n"); + break; + default: + FIXME("TKIND %d unhandled.\n",tattr->typekind); + break; + } + ITypeInfo_Release(tinfo2); + } V_VT(pVarResult) = tdesc->vt; /* HACK: VB5 likes this. Index: dlls/oleaut32/typelib.h =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/typelib.h,v retrieving revision 1.13 diff -u -r1.13 typelib.h --- dlls/oleaut32/typelib.h 10 Jul 2002 23:07:59 -0000 1.13 +++ dlls/oleaut32/typelib.h 28 Dec 2002 20:26:10 -0000 @@ -417,7 +417,7 @@ /*0e*/ WORD res0e; /*10*/ WORD res10; /*12*/ WORD res12; -/*14*/ WORD res14; +/*14*/ WORD tdescalias_vt; /* for TKIND_ALIAS */ /*16*/ WORD res16; /*18*/ WORD res18; /*1a*/ WORD res1a; @@ -457,6 +457,13 @@ } SLTG_EnumItem; #define SLTG_ENUMITEM_MAGIC 0x120a + +typedef struct { +/*00*/ WORD vt; /* vartype, 0xffff marks end. */ +/*02*/ WORD res02; /* ?, 0xffff marks end */ +} SLTG_AliasItem; + +#define SLTG_ALIASITEM_MAGIC 0x001d typedef struct {