oleaut32: non-dual dispinterfaces should be marshaled via IDispatch.

This commit is contained in:
Huw Davies 2007-05-17 15:29:41 +01:00 committed by Alexandre Julliard
parent f1da672df3
commit c24a53dc28
1 changed files with 118 additions and 49 deletions

View File

@ -320,49 +320,49 @@ _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
return hres;
}
/* Determine nr of functions. Since we use the toplevel interface and all
* inherited ones have lower numbers, we are ok to not to descent into
* the inheritance tree I think.
/*
* Determine the number of functions including all inherited functions.
* Note for non-dual dispinterfaces we simply return the size of IDispatch.
*/
static int _nroffuncs(ITypeInfo *tinfo) {
int n, i, j;
const FUNCDESC *fdesc;
HRESULT hres;
static HRESULT num_of_funcs(ITypeInfo *tinfo, unsigned int *num)
{
HRESULT hres;
TYPEATTR *attr;
ITypeInfo *tinfo2;
n=0;
*num = 0;
hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
if (hres) {
ERR("GetTypeAttr failed with %x\n",hres);
return hres;
}
/* look in inherited ifaces. */
for (j=0;j<attr->cImplTypes;j++) {
if(attr->typekind == TKIND_DISPATCH && (attr->wTypeFlags & TYPEFLAG_FDUAL))
{
HREFTYPE href;
hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);
if (hres) {
ERR("Did not find a reftype for interface offset %d?\n",j);
break;
hres = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href);
if(FAILED(hres))
{
ERR("Unable to get interface href from dual dispinterface\n");
goto end;
}
hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
if (hres) {
ERR("Did not find a typeinfo for reftype %d?\n",href);
continue;
if(FAILED(hres))
{
ERR("Unable to get interface from dual dispinterface\n");
goto end;
}
n += _nroffuncs(tinfo2);
hres = num_of_funcs(tinfo2, num);
ITypeInfo_Release(tinfo2);
}
ITypeInfo_ReleaseTypeAttr(tinfo, attr);
i = 0;
while (1) {
hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo,i,&fdesc);
if (hres)
return n;
n++;
i++;
else
{
*num = attr->cbSizeVft / 4;
}
/*NOTREACHED*/
end:
ITypeInfo_ReleaseTypeAttr(tinfo, attr);
return hres;
}
#ifdef __i386__
@ -1215,6 +1215,37 @@ static HRESULT get_funcdesc(ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual,
ERR("GetTypeAttr failed with %x\n",hr);
return hr;
}
if(attr->typekind == TKIND_DISPATCH)
{
if(attr->wTypeFlags & TYPEFLAG_FDUAL)
{
HREFTYPE href;
ITypeInfo *tinfo2;
hr = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href);
if(FAILED(hr))
{
ERR("Cannot get interface href from dual dispinterface\n");
ITypeInfo_ReleaseTypeAttr(tinfo, attr);
return hr;
}
hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
if(FAILED(hr))
{
ERR("Cannot get interface from dual dispinterface\n");
ITypeInfo_ReleaseTypeAttr(tinfo, attr);
return hr;
}
hr = get_funcdesc(tinfo2, iMethod, tactual, fdesc, iname, fname, num);
ITypeInfo_Release(tinfo2);
ITypeInfo_ReleaseTypeAttr(tinfo, attr);
return hr;
}
ERR("Shouldn't be called with a non-dual dispinterface\n");
return E_FAIL;
}
impl_types = attr->cImplTypes;
ITypeInfo_ReleaseTypeAttr(tinfo, attr);
@ -1699,9 +1730,10 @@ PSFacBuf_CreateProxy(
{
HRESULT hres;
ITypeInfo *tinfo;
int i, nroffuncs;
unsigned int i, nroffuncs;
TMProxyImpl *proxy;
TYPEATTR *typeattr;
BOOL defer_to_dispatch = FALSE;
TRACE("(...%s...)\n",debugstr_guid(riid));
hres = _get_typeinfo_for_iid(riid,&tinfo);
@ -1709,7 +1741,14 @@ PSFacBuf_CreateProxy(
ERR("No typeinfo for %s?\n",debugstr_guid(riid));
return hres;
}
nroffuncs = _nroffuncs(tinfo);
hres = num_of_funcs(tinfo, &nroffuncs);
if (FAILED(hres)) {
ERR("Cannot get number of functions for typeinfo %s\n",debugstr_guid(riid));
ITypeInfo_Release(tinfo);
return hres;
}
proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));
if (!proxy) return E_OUTOFMEMORY;
@ -1735,22 +1774,6 @@ PSFacBuf_CreateProxy(
proxy->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TMProxyImpl.crit");
proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
for (i=0;i<nroffuncs;i++) {
switch (i) {
case 0:
proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;
break;
case 1:
proxy->lpvtbl[i] = ProxyIUnknown_AddRef;
break;
case 2:
proxy->lpvtbl[i] = ProxyIUnknown_Release;
break;
default:
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
}
/* if we derive from IDispatch then defer to its proxy for its methods */
hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
@ -1774,15 +1797,61 @@ PSFacBuf_CreateProxy(
}
if (hres == S_OK)
{
proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount;
proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo;
proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames;
proxy->lpvtbl[6] = ProxyIDispatch_Invoke;
defer_to_dispatch = TRUE;
}
}
ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
}
for (i=0;i<nroffuncs;i++) {
switch (i) {
case 0:
proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;
break;
case 1:
proxy->lpvtbl[i] = ProxyIUnknown_AddRef;
break;
case 2:
proxy->lpvtbl[i] = ProxyIUnknown_Release;
break;
case 3:
if(!defer_to_dispatch)
{
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
else proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount;
break;
case 4:
if(!defer_to_dispatch)
{
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
else proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo;
break;
case 5:
if(!defer_to_dispatch)
{
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
else proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames;
break;
case 6:
if(!defer_to_dispatch)
{
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
else proxy->lpvtbl[6] = ProxyIDispatch_Invoke;
break;
default:
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
}
if (hres == S_OK)
{
*ppv = (LPVOID)proxy;