[PATCH 12/14] rpcrt4: Delegate to the parent if it is not IUnknown.
Zebediah Figura
z.figura12 at gmail.com
Sat Nov 3 18:07:24 CDT 2018
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
This differs from the old typelib marshaller's approach of using the
parent interface's methods directly; I find this approach to be
simpler given the architecture of stubless proxies.
dlls/rpcrt4/cpsf.h | 9 +++
dlls/rpcrt4/cstub.c | 11 +---
dlls/rpcrt4/ndr_typelib.c | 126 +++++++++++++++++++++++++++++---------
3 files changed, 107 insertions(+), 39 deletions(-)
diff --git a/dlls/rpcrt4/cpsf.h b/dlls/rpcrt4/cpsf.h
index c8980e526d..3cfbf77ff6 100644
--- a/dlls/rpcrt4/cpsf.h
+++ b/dlls/rpcrt4/cpsf.h
@@ -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 */
diff --git a/dlls/rpcrt4/cstub.c b/dlls/rpcrt4/cstub.c
index 838ed03653..77b0faf430 100644
--- a/dlls/rpcrt4/cstub.c
+++ b/dlls/rpcrt4/cstub.c
@@ -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);
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c
index 5eb72af8c7..b06139eae0 100644
--- a/dlls/rpcrt4/ndr_typelib.c
+++ b/dlls/rpcrt4/ndr_typelib.c
@@ -663,7 +663,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)
{
@@ -672,6 +672,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("proc %d\n", proc_idx);
@@ -680,9 +686,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++)
@@ -704,20 +710,20 @@ 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 typelen = oleaut_tfs_size, proclen = 0;
unsigned char *type, *proc;
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");
@@ -729,7 +735,7 @@ static HRESULT build_format_strings(ITypeInfo *typeinfo, WORD funcs,
typelen = oleaut_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;
@@ -746,9 +752,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;
@@ -800,7 +807,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)
@@ -833,6 +853,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);
@@ -852,7 +876,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;
@@ -865,6 +889,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);
@@ -877,12 +908,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;
@@ -905,10 +937,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))
{
@@ -918,7 +951,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);
@@ -933,18 +966,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);
@@ -954,6 +988,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);
@@ -964,38 +1005,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->stub.stub_buffer.lpVtbl = &stub->stub_vtbl.Vtbl;
+ stub->stub.stub_buffer.RefCount = 1;
- *stub_buffer = (IRpcStubBuffer *)&stub->stub;
+ *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;
@@ -1008,7 +1062,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))
{
@@ -1021,10 +1075,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);
--
2.19.1
More information about the wine-devel
mailing list