From 4beaa06e9dc6a47c5e41f0488da77e2daea07d89 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 2 Jan 2003 23:11:19 +0000 Subject: [PATCH] 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. --- dlls/oleaut32/typelib.c | 261 ++++++++++++++++++++++++++++++++++------ dlls/oleaut32/typelib.h | 9 +- 2 files changed, 229 insertions(+), 41 deletions(-) diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 7c1978f04ff..4920bf02a51 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -573,9 +573,6 @@ HRESULT WINAPI UnRegisterTypeLib( 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 +1027,13 @@ void dump_Variant(VARIANT * pvar) 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 +2730,58 @@ static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI, 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 ; icbExtra/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 +3071,16 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) 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 +3093,28 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) (*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 +3209,8 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface) 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 +3973,7 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( 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 +4177,89 @@ _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) { 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 +4279,18 @@ DispCallFunc( So we need to add a first parameter to the list of arguments, to supply the interface pointer */ argsize = 1; for (i=0;ifuncdesc);*/ switch (pFDesc->funcdesc.funckind) { case FUNC_PUREVIRTUAL: @@ -4208,18 +4365,8 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( if (icArgs) { 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 +4409,40 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( 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. diff --git a/dlls/oleaut32/typelib.h b/dlls/oleaut32/typelib.h index 7b4bd36013b..0c9d9b4f2d0 100644 --- a/dlls/oleaut32/typelib.h +++ b/dlls/oleaut32/typelib.h @@ -417,7 +417,7 @@ typedef struct { /*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; @@ -458,6 +458,13 @@ typedef struct { #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 { BYTE magic; /* 0x4c or 0x6c */