diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c index 6f15ed564d5..ab24b816a32 100644 --- a/dlls/rpcrt4/cproxy.c +++ b/dlls/rpcrt4/cproxy.c @@ -197,7 +197,7 @@ static const struct thunk *allocate_block( unsigned int num ) return block; } -static BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num ) +BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num ) { const void **entry = (const void **)(vtbl + 1); DWORD i, j; diff --git a/dlls/rpcrt4/cpsf.h b/dlls/rpcrt4/cpsf.h index 0ada0d16bb8..c8980e526d3 100644 --- a/dlls/rpcrt4/cpsf.h +++ b/dlls/rpcrt4/cpsf.h @@ -61,5 +61,6 @@ extern const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl DECLSPEC_HIDDEN; BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num) DECLSPEC_HIDDEN; HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv) DECLSPEC_HIDDEN; HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub) DECLSPEC_HIDDEN; +BOOL fill_stubless_table(IUnknownVtbl *vtbl, DWORD num) DECLSPEC_HIDDEN; #endif /* __WINE_CPSF_H */ diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index c0db6b78fff..25c4183ab4d 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -20,6 +20,7 @@ #define COBJMACROS #include "oaidl.h" +#define USE_STUBLESS_PROXY #include "rpcproxy.h" #include "wine/debug.h" #include "wine/heap.h" @@ -28,9 +29,62 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); +static HRESULT build_format_strings(ITypeInfo *typeinfo, WORD funcs, + const unsigned char **type_ret, const unsigned char **proc_ret, + unsigned short **offset_ret) +{ + return E_NOTIMPL; +} + +/* Common helper for Create{Proxy,Stub}FromTypeInfo(). */ +static HRESULT get_iface_info(ITypeInfo *typeinfo, WORD *funcs, WORD *parentfuncs) +{ + TYPEATTR *typeattr; + ITypeLib *typelib; + TLIBATTR *libattr; + SYSKIND syskind; + HRESULT hr; + + hr = ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, NULL); + if (FAILED(hr)) + return hr; + + hr = ITypeLib_GetLibAttr(typelib, &libattr); + if (FAILED(hr)) + { + ITypeLib_Release(typelib); + return hr; + } + syskind = libattr->syskind; + ITypeLib_ReleaseTLibAttr(typelib, libattr); + ITypeLib_Release(typelib); + + hr = ITypeInfo_GetTypeAttr(typeinfo, &typeattr); + if (FAILED(hr)) + return hr; + *funcs = typeattr->cFuncs; + *parentfuncs = typeattr->cbSizeVft / (syskind == SYS_WIN64 ? 8 : 4) - *funcs; + ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr); + + return S_OK; +} + +static void init_stub_desc(MIDL_STUB_DESC *desc) +{ + desc->pfnAllocate = NdrOleAllocate; + desc->pfnFree = NdrOleFree; + desc->Version = 0x50002; + /* type format string is initialized with proc format string and offset table */ +} + struct typelib_proxy { StdProxyImpl proxy; + IID iid; + MIDL_STUB_DESC stub_desc; + MIDL_STUBLESS_PROXY_INFO proxy_info; + CInterfaceProxyVtbl *proxy_vtbl; + unsigned short *offset_table; }; static ULONG WINAPI typelib_proxy_Release(IRpcProxyBuffer *iface) @@ -42,6 +96,12 @@ static ULONG WINAPI typelib_proxy_Release(IRpcProxyBuffer *iface) if (!refcount) { + if (proxy->proxy.pChannel) + IRpcProxyBuffer_Disconnect(&proxy->proxy.IRpcProxyBuffer_iface); + heap_free((void *)proxy->stub_desc.pFormatTypes); + heap_free((void *)proxy->proxy_info.ProcFormatString); + heap_free(proxy->offset_table); + heap_free(proxy->proxy_vtbl); heap_free(proxy); } return refcount; @@ -57,37 +117,81 @@ static const IRpcProxyBufferVtbl typelib_proxy_vtbl = }; static HRESULT typelib_proxy_init(struct typelib_proxy *proxy, IUnknown *outer, - IRpcProxyBuffer **proxy_buffer, void **out) + ULONG count, IRpcProxyBuffer **proxy_buffer, void **out) { + if (!fill_stubless_table((IUnknownVtbl *)proxy->proxy_vtbl->Vtbl, count)) + return E_OUTOFMEMORY; + if (!outer) outer = (IUnknown *)&proxy->proxy; proxy->proxy.IRpcProxyBuffer_iface.lpVtbl = &typelib_proxy_vtbl; + proxy->proxy.PVtbl = proxy->proxy_vtbl->Vtbl; proxy->proxy.RefCount = 1; + proxy->proxy.piid = proxy->proxy_vtbl->header.piid; proxy->proxy.pUnkOuter = outer; *proxy_buffer = &proxy->proxy.IRpcProxyBuffer_iface; + *out = &proxy->proxy.PVtbl; + IUnknown_AddRef((IUnknown *)*out); - return E_NOTIMPL; + return S_OK; } HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy_buffer, void **out) { struct typelib_proxy *proxy; + WORD funcs, parentfuncs, i; HRESULT hr; - TRACE("typeinfo %p, outer %p, iid %s, proxy %p, out %p.\n", + TRACE("typeinfo %p, outer %p, iid %s, proxy_buffer %p, out %p.\n", typeinfo, outer, debugstr_guid(iid), proxy_buffer, out); + hr = get_iface_info(typeinfo, &funcs, &parentfuncs); + if (FAILED(hr)) + return hr; + if (!(proxy = heap_alloc_zero(sizeof(*proxy)))) { ERR("Failed to allocate proxy object.\n"); return E_OUTOFMEMORY; } - hr = typelib_proxy_init(proxy, outer, proxy_buffer, out); - if (FAILED(hr)) + init_stub_desc(&proxy->stub_desc); + proxy->proxy_info.pStubDesc = &proxy->stub_desc; + + proxy->proxy_vtbl = heap_alloc_zero(sizeof(proxy->proxy_vtbl->header) + (funcs + parentfuncs) * sizeof(void *)); + if (!proxy->proxy_vtbl) + { + ERR("Failed to allocate proxy vtbl.\n"); heap_free(proxy); + return E_OUTOFMEMORY; + } + proxy->proxy_vtbl->header.pStublessProxyInfo = &proxy->proxy_info; + proxy->iid = *iid; + proxy->proxy_vtbl->header.piid = &proxy->iid; + for (i = 0; i < funcs; i++) + proxy->proxy_vtbl->Vtbl[3 + i] = (void *)-1; + + hr = build_format_strings(typeinfo, funcs, &proxy->stub_desc.pFormatTypes, + &proxy->proxy_info.ProcFormatString, &proxy->offset_table); + if (FAILED(hr)) + { + heap_free(proxy->proxy_vtbl); + heap_free(proxy); + return hr; + } + proxy->proxy_info.FormatStringOffset = &proxy->offset_table[-3]; + + hr = typelib_proxy_init(proxy, outer, funcs + parentfuncs, proxy_buffer, out); + if (FAILED(hr)) + { + heap_free((void *)proxy->stub_desc.pFormatTypes); + heap_free((void *)proxy->proxy_info.ProcFormatString); + heap_free((void *)proxy->offset_table); + heap_free(proxy->proxy_vtbl); + heap_free(proxy); + } return hr; }