Hi.
I've tryed to run game Project Entropia and I got segmentation fault because of a bug in OLE.
I've hacked code and I found two bugs:
1. ITypeInfo has back pointer to ITypeLib, but it's possible (and happened) that ITypeLib is
destroyed and later ITypeInfo calls its function. I've solve this problem by call ITypeLib_AddRef
while creating ITypeInfo (and ITypeLib_Release while destroying ITypeInfo).
2. ITypeInfo_Invoke doesn't support optional parameters. I've added support for cParamsOpt>0.
MSDN says that optional parameter is when VARTYPE equals VT_EMPTY, but in my case
it was a VT_BYREF | VT_VARIANT type but the pointer was NULL. When I treated it as
VT_EMPTY, it was OK.
I enclose my patch. My knownlage about OLE is sparse so I'm not able to test this.
Thanks, Jacek
Index: dlls/oleaut32/typelib.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/typelib.c,v retrieving revision 1.116 diff -u -r1.116 typelib.c --- dlls/oleaut32/typelib.c 6 Jul 2004 21:28:13 -0000 1.116 +++ dlls/oleaut32/typelib.c 6 Aug 2004 22:47:20 -0000 @@ -1999,6 +1999,7 @@ MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx , pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase)); /* this is where we are coming from */ + ITypeLib2_AddRef((ITypeLib*)pLibInfo); ptiRet->pTypeLib = pLibInfo; ptiRet->index=count; /* fill in the typeattr fields */ @@ -3265,6 +3266,7 @@ return NULL; } *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor(); + pTypeLibImpl->ref++; (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl; (*ppTypeInfoImpl)->index = i; (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR( @@ -4116,6 +4118,9 @@ ITypeInfo_Release((ITypeInfo*)This->next); } + if (This->pTypeLib) + ITypeLib2_Release((ITypeLib*)This->pTypeLib); + HeapFree(GetProcessHeap(),0,This); return 0; } @@ -4736,6 +4741,14 @@ if (i<pDispParams->cArgs) { VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1]; TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc; + if (pFDesc->funcdesc.cParamsOpt>0 && i>=pFDesc->funcdesc.cParams-pFDesc->funcdesc.cParamsOpt) { + if(V_VT(arg) == VT_EMPTY + || ((V_VT(arg) & VT_BYREF) && !V_BYREF(arg))) { /* I'm not sure if it's correct but it works */ + V_VT(arg) = VT_ERROR; + V_ERROR(arg) = DISP_E_PARAMNOTFOUND; + arglen = _argsize(VT_ERROR); + } + } hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt); if (FAILED(hres)) return hres; argspos += arglen; @@ -4756,7 +4769,7 @@ args2pos += arglen; } } - if (pFDesc->funcdesc.cParamsOpt) + if (pFDesc->funcdesc.cParamsOpt<0) FIXME("Does not support optional parameters (%d)\n", pFDesc->funcdesc.cParamsOpt );