rpcrt4: Delegate to the parent if it is not IUnknown.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f6b1341aa2
commit
d3bc9721f7
3 changed files with 107 additions and 39 deletions
|
@ -37,6 +37,13 @@ typedef struct
|
|||
IRpcChannelBuffer *pChannel;
|
||||
} StdProxyImpl;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IUnknownVtbl *base_obj;
|
||||
IRpcStubBuffer *base_stub;
|
||||
CStdStubBuffer stub_buffer;
|
||||
} cstdstubbuffer_delegating_t;
|
||||
|
||||
HRESULT StdProxy_Construct(REFIID riid, LPUNKNOWN pUnkOuter, const ProxyFileInfo *ProxyInfo,
|
||||
int Index, LPPSFACTORYBUFFER pPSFactory, LPRPCPROXYBUFFER *ppProxy,
|
||||
LPVOID *ppvObj) DECLSPEC_HIDDEN;
|
||||
|
@ -62,5 +69,7 @@ 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;
|
||||
IUnknownVtbl *get_delegating_vtbl(DWORD num_methods) DECLSPEC_HIDDEN;
|
||||
void release_delegating_vtbl(IUnknownVtbl *vtbl) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif /* __WINE_CPSF_H */
|
||||
|
|
|
@ -50,13 +50,6 @@ static LONG WINAPI stub_filter(EXCEPTION_POINTERS *eptr)
|
|||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IUnknownVtbl *base_obj;
|
||||
IRpcStubBuffer *base_stub;
|
||||
CStdStubBuffer stub_buffer;
|
||||
} cstdstubbuffer_delegating_t;
|
||||
|
||||
static inline cstdstubbuffer_delegating_t *impl_from_delegating( IRpcStubBuffer *iface )
|
||||
{
|
||||
return CONTAINING_RECORD(iface, cstdstubbuffer_delegating_t, stub_buffer);
|
||||
|
@ -260,7 +253,7 @@ BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static IUnknownVtbl *get_delegating_vtbl(DWORD num_methods)
|
||||
IUnknownVtbl *get_delegating_vtbl(DWORD num_methods)
|
||||
{
|
||||
IUnknownVtbl *ret;
|
||||
|
||||
|
@ -296,7 +289,7 @@ static IUnknownVtbl *get_delegating_vtbl(DWORD num_methods)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void release_delegating_vtbl(IUnknownVtbl *vtbl)
|
||||
void release_delegating_vtbl(IUnknownVtbl *vtbl)
|
||||
{
|
||||
ref_counted_vtbl *table = (ref_counted_vtbl*)((DWORD *)vtbl - 1);
|
||||
|
||||
|
|
|
@ -704,7 +704,7 @@ static void write_proc_func_header(ITypeInfo *typeinfo, FUNCDESC *desc,
|
|||
WRITE_CHAR (proc, *proclen, desc->cParams + 1); /* incl. return value */
|
||||
}
|
||||
|
||||
static HRESULT write_iface_fs(ITypeInfo *typeinfo, WORD funcs,
|
||||
static HRESULT write_iface_fs(ITypeInfo *typeinfo, WORD funcs, WORD parentfuncs,
|
||||
unsigned char *type, size_t *typelen, unsigned char *proc,
|
||||
size_t *proclen, unsigned short *offset)
|
||||
{
|
||||
|
@ -713,6 +713,12 @@ static HRESULT write_iface_fs(ITypeInfo *typeinfo, WORD funcs,
|
|||
FUNCDESC *desc;
|
||||
HRESULT hr;
|
||||
|
||||
for (proc_idx = 3; proc_idx < parentfuncs; proc_idx++)
|
||||
{
|
||||
if (offset)
|
||||
offset[proc_idx - 3] = -1;
|
||||
}
|
||||
|
||||
for (proc_idx = 0; proc_idx < funcs; proc_idx++)
|
||||
{
|
||||
TRACE("Writing procedure %d.\n", proc_idx);
|
||||
|
@ -721,9 +727,9 @@ static HRESULT write_iface_fs(ITypeInfo *typeinfo, WORD funcs,
|
|||
if (FAILED(hr)) return hr;
|
||||
|
||||
if (offset)
|
||||
offset[proc_idx] = *proclen;
|
||||
offset[proc_idx + parentfuncs - 3] = *proclen;
|
||||
|
||||
write_proc_func_header(typeinfo, desc, proc_idx + 3, proc, proclen);
|
||||
write_proc_func_header(typeinfo, desc, proc_idx + parentfuncs, proc, proclen);
|
||||
|
||||
stack_offset = sizeof(void *); /* This */
|
||||
for (param_idx = 0; param_idx < desc->cParams; param_idx++)
|
||||
|
@ -748,8 +754,8 @@ static HRESULT write_iface_fs(ITypeInfo *typeinfo, WORD funcs,
|
|||
}
|
||||
|
||||
static HRESULT build_format_strings(ITypeInfo *typeinfo, WORD funcs,
|
||||
const unsigned char **type_ret, const unsigned char **proc_ret,
|
||||
unsigned short **offset_ret)
|
||||
WORD parentfuncs, const unsigned char **type_ret,
|
||||
const unsigned char **proc_ret, unsigned short **offset_ret)
|
||||
{
|
||||
size_t tfs_size;
|
||||
const unsigned char *tfs = get_type_format_string( &tfs_size );
|
||||
|
@ -758,12 +764,12 @@ static HRESULT build_format_strings(ITypeInfo *typeinfo, WORD funcs,
|
|||
unsigned short *offset;
|
||||
HRESULT hr;
|
||||
|
||||
hr = write_iface_fs(typeinfo, funcs, NULL, &typelen, NULL, &proclen, NULL);
|
||||
hr = write_iface_fs(typeinfo, funcs, parentfuncs, NULL, &typelen, NULL, &proclen, NULL);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
type = heap_alloc(typelen);
|
||||
proc = heap_alloc(proclen);
|
||||
offset = heap_alloc(funcs * sizeof(*offset));
|
||||
offset = heap_alloc((parentfuncs + funcs - 3) * sizeof(*offset));
|
||||
if (!type || !proc || !offset)
|
||||
{
|
||||
ERR("Failed to allocate format strings.\n");
|
||||
|
@ -775,7 +781,7 @@ static HRESULT build_format_strings(ITypeInfo *typeinfo, WORD funcs,
|
|||
typelen = tfs_size;
|
||||
proclen = 0;
|
||||
|
||||
hr = write_iface_fs(typeinfo, funcs, type, &typelen, proc, &proclen, offset);
|
||||
hr = write_iface_fs(typeinfo, funcs, parentfuncs, type, &typelen, proc, &proclen, offset);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
*type_ret = type;
|
||||
|
@ -792,9 +798,10 @@ err:
|
|||
}
|
||||
|
||||
/* Common helper for Create{Proxy,Stub}FromTypeInfo(). */
|
||||
static HRESULT get_iface_info(ITypeInfo **typeinfo, WORD *funcs, WORD *parentfuncs)
|
||||
static HRESULT get_iface_info(ITypeInfo **typeinfo, WORD *funcs, WORD *parentfuncs,
|
||||
GUID *parentiid)
|
||||
{
|
||||
ITypeInfo *real_typeinfo;
|
||||
ITypeInfo *real_typeinfo, *parentinfo;
|
||||
TYPEATTR *typeattr;
|
||||
ITypeLib *typelib;
|
||||
TLIBATTR *libattr;
|
||||
|
@ -846,7 +853,20 @@ static HRESULT get_iface_info(ITypeInfo **typeinfo, WORD *funcs, WORD *parentfun
|
|||
*parentfuncs = typeattr->cbSizeVft / (syskind == SYS_WIN64 ? 8 : 4) - *funcs;
|
||||
ITypeInfo_ReleaseTypeAttr(*typeinfo, typeattr);
|
||||
|
||||
return S_OK;
|
||||
hr = ITypeInfo_GetRefTypeOfImplType(*typeinfo, 0, &reftype);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
hr = ITypeInfo_GetRefTypeInfo(*typeinfo, reftype, &parentinfo);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
hr = ITypeInfo_GetTypeAttr(parentinfo, &typeattr);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
*parentiid = typeattr->guid;
|
||||
ITypeInfo_ReleaseTypeAttr(parentinfo, typeattr);
|
||||
ITypeInfo_Release(parentinfo);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static void init_stub_desc(MIDL_STUB_DESC *desc)
|
||||
|
@ -879,6 +899,10 @@ static ULONG WINAPI typelib_proxy_Release(IRpcProxyBuffer *iface)
|
|||
{
|
||||
if (proxy->proxy.pChannel)
|
||||
IRpcProxyBuffer_Disconnect(&proxy->proxy.IRpcProxyBuffer_iface);
|
||||
if (proxy->proxy.base_object)
|
||||
IUnknown_Release(proxy->proxy.base_object);
|
||||
if (proxy->proxy.base_proxy)
|
||||
IRpcProxyBuffer_Release(proxy->proxy.base_proxy);
|
||||
heap_free((void *)proxy->stub_desc.pFormatTypes);
|
||||
heap_free((void *)proxy->proxy_info.ProcFormatString);
|
||||
heap_free(proxy->offset_table);
|
||||
|
@ -898,7 +922,7 @@ static const IRpcProxyBufferVtbl typelib_proxy_vtbl =
|
|||
};
|
||||
|
||||
static HRESULT typelib_proxy_init(struct typelib_proxy *proxy, IUnknown *outer,
|
||||
ULONG count, IRpcProxyBuffer **proxy_buffer, void **out)
|
||||
ULONG count, const GUID *parentiid, IRpcProxyBuffer **proxy_buffer, void **out)
|
||||
{
|
||||
if (!fill_stubless_table((IUnknownVtbl *)proxy->proxy_vtbl->Vtbl, count))
|
||||
return E_OUTOFMEMORY;
|
||||
|
@ -911,6 +935,13 @@ static HRESULT typelib_proxy_init(struct typelib_proxy *proxy, IUnknown *outer,
|
|||
proxy->proxy.piid = proxy->proxy_vtbl->header.piid;
|
||||
proxy->proxy.pUnkOuter = outer;
|
||||
|
||||
if (!IsEqualGUID(parentiid, &IID_IUnknown))
|
||||
{
|
||||
HRESULT hr = create_proxy(parentiid, NULL, &proxy->proxy.base_proxy,
|
||||
(void **)&proxy->proxy.base_object);
|
||||
if (FAILED(hr)) return hr;
|
||||
}
|
||||
|
||||
*proxy_buffer = &proxy->proxy.IRpcProxyBuffer_iface;
|
||||
*out = &proxy->proxy.PVtbl;
|
||||
IUnknown_AddRef((IUnknown *)*out);
|
||||
|
@ -923,12 +954,13 @@ HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, IUnknown *outer,
|
|||
{
|
||||
struct typelib_proxy *proxy;
|
||||
WORD funcs, parentfuncs, i;
|
||||
GUID parentiid;
|
||||
HRESULT hr;
|
||||
|
||||
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);
|
||||
hr = get_iface_info(&typeinfo, &funcs, &parentfuncs, &parentiid);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
|
@ -951,10 +983,11 @@ HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, IUnknown *outer,
|
|||
proxy->proxy_vtbl->header.pStublessProxyInfo = &proxy->proxy_info;
|
||||
proxy->iid = *iid;
|
||||
proxy->proxy_vtbl->header.piid = &proxy->iid;
|
||||
fill_delegated_proxy_table((IUnknownVtbl *)proxy->proxy_vtbl->Vtbl, parentfuncs);
|
||||
for (i = 0; i < funcs; i++)
|
||||
proxy->proxy_vtbl->Vtbl[3 + i] = (void *)-1;
|
||||
proxy->proxy_vtbl->Vtbl[parentfuncs + i] = (void *)-1;
|
||||
|
||||
hr = build_format_strings(typeinfo, funcs, &proxy->stub_desc.pFormatTypes,
|
||||
hr = build_format_strings(typeinfo, funcs, parentfuncs, &proxy->stub_desc.pFormatTypes,
|
||||
&proxy->proxy_info.ProcFormatString, &proxy->offset_table);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -964,7 +997,7 @@ HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, IUnknown *outer,
|
|||
}
|
||||
proxy->proxy_info.FormatStringOffset = &proxy->offset_table[-3];
|
||||
|
||||
hr = typelib_proxy_init(proxy, outer, funcs + parentfuncs, proxy_buffer, out);
|
||||
hr = typelib_proxy_init(proxy, outer, funcs + parentfuncs, &parentiid, proxy_buffer, out);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
heap_free((void *)proxy->stub_desc.pFormatTypes);
|
||||
|
@ -979,18 +1012,19 @@ HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, IUnknown *outer,
|
|||
|
||||
struct typelib_stub
|
||||
{
|
||||
CStdStubBuffer stub;
|
||||
cstdstubbuffer_delegating_t stub;
|
||||
IID iid;
|
||||
MIDL_STUB_DESC stub_desc;
|
||||
MIDL_SERVER_INFO server_info;
|
||||
CInterfaceStubVtbl stub_vtbl;
|
||||
unsigned short *offset_table;
|
||||
PRPC_STUB_FUNCTION *dispatch_table;
|
||||
};
|
||||
|
||||
static ULONG WINAPI typelib_stub_Release(IRpcStubBuffer *iface)
|
||||
{
|
||||
struct typelib_stub *stub = CONTAINING_RECORD(iface, struct typelib_stub, stub);
|
||||
ULONG refcount = InterlockedDecrement(&stub->stub.RefCount);
|
||||
struct typelib_stub *stub = CONTAINING_RECORD(iface, struct typelib_stub, stub.stub_buffer);
|
||||
ULONG refcount = InterlockedDecrement(&stub->stub.stub_buffer.RefCount);
|
||||
|
||||
TRACE("(%p) decreasing refs to %d\n", stub, refcount);
|
||||
|
||||
|
@ -1000,6 +1034,13 @@ static ULONG WINAPI typelib_stub_Release(IRpcStubBuffer *iface)
|
|||
We'll leave it in for the time being. */
|
||||
IRpcStubBuffer_Disconnect(iface);
|
||||
|
||||
if (stub->stub.base_stub)
|
||||
{
|
||||
IRpcStubBuffer_Release(stub->stub.base_stub);
|
||||
release_delegating_vtbl(stub->stub.base_obj);
|
||||
heap_free(stub->dispatch_table);
|
||||
}
|
||||
|
||||
heap_free((void *)stub->stub_desc.pFormatTypes);
|
||||
heap_free((void *)stub->server_info.ProcString);
|
||||
heap_free(stub->offset_table);
|
||||
|
@ -1010,38 +1051,51 @@ static ULONG WINAPI typelib_stub_Release(IRpcStubBuffer *iface)
|
|||
}
|
||||
|
||||
static HRESULT typelib_stub_init(struct typelib_stub *stub, IUnknown *server,
|
||||
IRpcStubBuffer **stub_buffer)
|
||||
const GUID *parentiid, IRpcStubBuffer **stub_buffer)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = IUnknown_QueryInterface(server, stub->stub_vtbl.header.piid,
|
||||
(void **)&stub->stub.pvServerObject);
|
||||
(void **)&stub->stub.stub_buffer.pvServerObject);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WARN("Failed to get interface %s, hr %#x.\n",
|
||||
debugstr_guid(stub->stub_vtbl.header.piid), hr);
|
||||
stub->stub.pvServerObject = server;
|
||||
stub->stub.stub_buffer.pvServerObject = server;
|
||||
IUnknown_AddRef(server);
|
||||
}
|
||||
|
||||
stub->stub.lpVtbl = &stub->stub_vtbl.Vtbl;
|
||||
stub->stub.RefCount = 1;
|
||||
if (!IsEqualGUID(parentiid, &IID_IUnknown))
|
||||
{
|
||||
stub->stub.base_obj = get_delegating_vtbl(stub->stub_vtbl.header.DispatchTableCount);
|
||||
hr = create_stub(parentiid, (IUnknown *)&stub->stub.base_obj, &stub->stub.base_stub);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
release_delegating_vtbl(stub->stub.base_obj);
|
||||
IUnknown_Release(stub->stub.stub_buffer.pvServerObject);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
*stub_buffer = (IRpcStubBuffer *)&stub->stub;
|
||||
stub->stub.stub_buffer.lpVtbl = &stub->stub_vtbl.Vtbl;
|
||||
stub->stub.stub_buffer.RefCount = 1;
|
||||
|
||||
*stub_buffer = (IRpcStubBuffer *)&stub->stub.stub_buffer;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CreateStubFromTypeInfo(ITypeInfo *typeinfo, REFIID iid,
|
||||
IUnknown *server, IRpcStubBuffer **stub_buffer)
|
||||
{
|
||||
WORD funcs, parentfuncs, i;
|
||||
struct typelib_stub *stub;
|
||||
WORD funcs, parentfuncs;
|
||||
GUID parentiid;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("typeinfo %p, iid %s, server %p, stub_buffer %p.\n",
|
||||
typeinfo, debugstr_guid(iid), server, stub_buffer);
|
||||
|
||||
hr = get_iface_info(&typeinfo, &funcs, &parentfuncs);
|
||||
hr = get_iface_info(&typeinfo, &funcs, &parentfuncs, &parentiid);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
|
@ -1054,7 +1108,7 @@ HRESULT WINAPI CreateStubFromTypeInfo(ITypeInfo *typeinfo, REFIID iid,
|
|||
init_stub_desc(&stub->stub_desc);
|
||||
stub->server_info.pStubDesc = &stub->stub_desc;
|
||||
|
||||
hr = build_format_strings(typeinfo, funcs, &stub->stub_desc.pFormatTypes,
|
||||
hr = build_format_strings(typeinfo, funcs, parentfuncs, &stub->stub_desc.pFormatTypes,
|
||||
&stub->server_info.ProcString, &stub->offset_table);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -1067,10 +1121,22 @@ HRESULT WINAPI CreateStubFromTypeInfo(ITypeInfo *typeinfo, REFIID iid,
|
|||
stub->stub_vtbl.header.piid = &stub->iid;
|
||||
stub->stub_vtbl.header.pServerInfo = &stub->server_info;
|
||||
stub->stub_vtbl.header.DispatchTableCount = funcs + parentfuncs;
|
||||
stub->stub_vtbl.Vtbl = CStdStubBuffer_Vtbl;
|
||||
|
||||
if (!IsEqualGUID(&parentiid, &IID_IUnknown))
|
||||
{
|
||||
stub->dispatch_table = heap_alloc((funcs + parentfuncs) * sizeof(void *));
|
||||
for (i = 3; i < parentfuncs; i++)
|
||||
stub->dispatch_table[i - 3] = NdrStubForwardingFunction;
|
||||
for (; i < funcs + parentfuncs; i++)
|
||||
stub->dispatch_table[i - 3] = (PRPC_STUB_FUNCTION)NdrStubCall2;
|
||||
stub->stub_vtbl.header.pDispatchTable = &stub->dispatch_table[-3];
|
||||
stub->stub_vtbl.Vtbl = CStdStubBuffer_Delegating_Vtbl;
|
||||
}
|
||||
else
|
||||
stub->stub_vtbl.Vtbl = CStdStubBuffer_Vtbl;
|
||||
stub->stub_vtbl.Vtbl.Release = typelib_stub_Release;
|
||||
|
||||
hr = typelib_stub_init(stub, server, stub_buffer);
|
||||
hr = typelib_stub_init(stub, server, &parentiid, stub_buffer);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
heap_free((void *)stub->stub_desc.pFormatTypes);
|
||||
|
|
Loading…
Add table
Reference in a new issue