This patch series rewrites the Automation type library marshaller on top of NDR Oif-mode stubless proxies, after the conversation here:
https://www.winehq.org/pipermail/wine-devel/2017-November/119456.html
The idea is essentially to build the format strings and other proxy-related structures dynamically, and then pass those to the standard cproxy/cstub implementations. The code was written largely based on widl and ends up having a fair amount of the same structure.
Zebediah Figura (14): rpcrt4: Add a stub implementation of CreateProxyFromTypeInfo(). rpcrt4: Add a stub implementation of CreateStubFromTypeInfo(). rpcrt4: Build the typelib proxy headers. rpcrt4: Build the typelib stub headers. rpcrt4: Write the function header into the procedure format string. rpcrt4: Write parameter signatures into the procedure format string. rpcrt4: Write type format strings for pointers. rpcrt4: Write type format strings for fixed arrays. rpcrt4: Write type format strings for fixed structs. rpcrt4: Write type format strings for Automation types. rpcrt4: Retrieve the underlying interface for dual interfaces. rpcrt4: Delegate to the parent if it is not IUnknown. rpcrt4: Write the floating-point mask on x86-64. oleaut32: Rip out the old typelib marshaller.
Makefile.in | 1 + dlls/oleaut32/Makefile.in | 1 - dlls/oleaut32/oleaut.c | 284 +++- dlls/oleaut32/tests/tmarshal.c | 24 +- dlls/oleaut32/tmarshal.c | 2351 -------------------------------- dlls/oleaut32/typelib.c | 32 - dlls/oleaut32/typelib.h | 6 - dlls/rpcrt4/Makefile.in | 22 +- dlls/rpcrt4/cproxy.c | 70 +- dlls/rpcrt4/cpsf.h | 30 + dlls/rpcrt4/cstub.c | 11 +- dlls/rpcrt4/ndr_typelib.c | 1127 +++++++++++++++ 12 files changed, 1443 insertions(+), 2516 deletions(-) delete mode 100644 dlls/oleaut32/tmarshal.c create mode 100644 dlls/rpcrt4/ndr_typelib.c
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/Makefile.in | 1 + dlls/rpcrt4/cproxy.c | 47 ++------------------ dlls/rpcrt4/cpsf.h | 20 +++++++++ dlls/rpcrt4/ndr_typelib.c | 93 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 43 deletions(-) create mode 100644 dlls/rpcrt4/ndr_typelib.c
diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in index 92070ea2c3..ad67edf92e 100644 --- a/dlls/rpcrt4/Makefile.in +++ b/dlls/rpcrt4/Makefile.in @@ -15,6 +15,7 @@ C_SRCS = \ ndr_marshall.c \ ndr_ole.c \ ndr_stubless.c \ + ndr_typelib.c \ rpc_assoc.c \ rpc_async.c \ rpc_binding.c \ diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c index 71ae560929..7ca05e7248 100644 --- a/dlls/rpcrt4/cproxy.c +++ b/dlls/rpcrt4/cproxy.c @@ -42,21 +42,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(ole);
-/* I don't know what MS's std proxy structure looks like, - so this probably doesn't match, but that shouldn't matter */ -typedef struct { - IRpcProxyBuffer IRpcProxyBuffer_iface; - LPVOID *PVtbl; - LONG RefCount; - const IID* piid; - LPUNKNOWN pUnkOuter; - IUnknown *base_object; /* must be at offset 0x10 from PVtbl */ - IRpcProxyBuffer *base_proxy; - PCInterfaceName name; - LPPSFACTORYBUFFER pPSFactory; - LPRPCCHANNELBUFFER pChannel; -} StdProxyImpl; - static const IRpcProxyBufferVtbl StdProxy_Vtbl;
static inline StdProxyImpl *impl_from_IRpcProxyBuffer(IRpcProxyBuffer *iface) @@ -296,9 +281,7 @@ HRESULT StdProxy_Construct(REFIID riid, return S_OK; }
-static HRESULT WINAPI StdProxy_QueryInterface(LPRPCPROXYBUFFER iface, - REFIID riid, - LPVOID *obj) +HRESULT WINAPI StdProxy_QueryInterface(IRpcProxyBuffer *iface, REFIID riid, void **obj) { StdProxyImpl *This = impl_from_IRpcProxyBuffer(iface); TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj); @@ -319,7 +302,7 @@ static HRESULT WINAPI StdProxy_QueryInterface(LPRPCPROXYBUFFER iface, return E_NOINTERFACE; }
-static ULONG WINAPI StdProxy_AddRef(LPRPCPROXYBUFFER iface) +ULONG WINAPI StdProxy_AddRef(IRpcProxyBuffer *iface) { StdProxyImpl *This = impl_from_IRpcProxyBuffer(iface); TRACE("(%p)->AddRef()\n",This); @@ -349,8 +332,7 @@ static ULONG WINAPI StdProxy_Release(LPRPCPROXYBUFFER iface) return refs; }
-static HRESULT WINAPI StdProxy_Connect(LPRPCPROXYBUFFER iface, - LPRPCCHANNELBUFFER pChannel) +HRESULT WINAPI StdProxy_Connect(IRpcProxyBuffer *iface, IRpcChannelBuffer *pChannel) { StdProxyImpl *This = impl_from_IRpcProxyBuffer(iface); TRACE("(%p)->Connect(%p)\n",This,pChannel); @@ -361,7 +343,7 @@ static HRESULT WINAPI StdProxy_Connect(LPRPCPROXYBUFFER iface, return S_OK; }
-static VOID WINAPI StdProxy_Disconnect(LPRPCPROXYBUFFER iface) +void WINAPI StdProxy_Disconnect(IRpcProxyBuffer *iface) { StdProxyImpl *This = impl_from_IRpcProxyBuffer(iface); TRACE("(%p)->Disconnect()\n",This); @@ -531,27 +513,6 @@ HRESULT WINAPI NdrProxyErrorHandler(DWORD dwExceptionCode) return HRESULT_FROM_WIN32(dwExceptionCode); }
-HRESULT WINAPI -CreateProxyFromTypeInfo( LPTYPEINFO pTypeInfo, LPUNKNOWN pUnkOuter, REFIID riid, - LPRPCPROXYBUFFER *ppProxy, LPVOID *ppv ) -{ - typedef INT (WINAPI *MessageBoxA)(HWND,LPCSTR,LPCSTR,UINT); - HMODULE hUser32 = LoadLibraryA("user32"); - MessageBoxA pMessageBoxA = (void *)GetProcAddress(hUser32, "MessageBoxA"); - - FIXME("%p %p %s %p %p\n", pTypeInfo, pUnkOuter, debugstr_guid(riid), ppProxy, ppv); - if (pMessageBoxA) - { - pMessageBoxA(NULL, - "The native implementation of OLEAUT32.DLL cannot be used " - "with Wine's RPCRT4.DLL. Remove OLEAUT32.DLL and try again.\n", - "Wine: Unimplemented CreateProxyFromTypeInfo", - 0x10); - ExitProcess(1); - } - return E_NOTIMPL; -} - HRESULT WINAPI CreateStubFromTypeInfo(ITypeInfo *pTypeInfo, REFIID riid, IUnknown *pUnkServer, IRpcStubBuffer **ppStub ) diff --git a/dlls/rpcrt4/cpsf.h b/dlls/rpcrt4/cpsf.h index 964fb4551f..0ada0d16bb 100644 --- a/dlls/rpcrt4/cpsf.h +++ b/dlls/rpcrt4/cpsf.h @@ -21,9 +21,29 @@ #ifndef __WINE_CPSF_H #define __WINE_CPSF_H
+typedef struct +{ + IRpcProxyBuffer IRpcProxyBuffer_iface; + void **PVtbl; + LONG RefCount; + const IID *piid; + IUnknown *pUnkOuter; + /* offset of base_object from PVtbl must match assembly thunks; see + * fill_delegated_proxy_table() */ + IUnknown *base_object; + IRpcProxyBuffer *base_proxy; + PCInterfaceName name; + IPSFactoryBuffer *pPSFactory; + IRpcChannelBuffer *pChannel; +} StdProxyImpl; + HRESULT StdProxy_Construct(REFIID riid, LPUNKNOWN pUnkOuter, const ProxyFileInfo *ProxyInfo, int Index, LPPSFACTORYBUFFER pPSFactory, LPRPCPROXYBUFFER *ppProxy, LPVOID *ppvObj) DECLSPEC_HIDDEN; +HRESULT WINAPI StdProxy_QueryInterface(IRpcProxyBuffer *iface, REFIID iid, void **obj) DECLSPEC_HIDDEN; +ULONG WINAPI StdProxy_AddRef(IRpcProxyBuffer *iface) DECLSPEC_HIDDEN; +HRESULT WINAPI StdProxy_Connect(IRpcProxyBuffer *iface, IRpcChannelBuffer *channel) DECLSPEC_HIDDEN; +void WINAPI StdProxy_Disconnect(IRpcProxyBuffer *iface) DECLSPEC_HIDDEN;
HRESULT CStdStubBuffer_Construct(REFIID riid, LPUNKNOWN pUnkServer, PCInterfaceName name, CInterfaceStubVtbl *vtbl, LPPSFACTORYBUFFER pPSFactory, diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c new file mode 100644 index 0000000000..13075ac571 --- /dev/null +++ b/dlls/rpcrt4/ndr_typelib.c @@ -0,0 +1,93 @@ +/* + * Type library proxy/stub implementation + * + * Copyright 2018 Zebediah Figura + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "oaidl.h" +#include "rpcproxy.h" +#include "wine/debug.h" +#include "wine/heap.h" + +#include "cpsf.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +struct typelib_proxy +{ + StdProxyImpl proxy; +}; + +static ULONG WINAPI typelib_proxy_Release(IRpcProxyBuffer *iface) +{ + struct typelib_proxy *proxy = CONTAINING_RECORD(iface, struct typelib_proxy, proxy.IRpcProxyBuffer_iface); + ULONG refcount = InterlockedDecrement(&proxy->proxy.RefCount); + + TRACE("(%p) decreasing refs to %d\n", proxy, refcount); + + if (!refcount) + { + heap_free(proxy); + } + return refcount; +} + +static const IRpcProxyBufferVtbl typelib_proxy_vtbl = +{ + StdProxy_QueryInterface, + StdProxy_AddRef, + typelib_proxy_Release, + StdProxy_Connect, + StdProxy_Disconnect, +}; + +static HRESULT typelib_proxy_init(struct typelib_proxy *proxy, IUnknown *outer, + IRpcProxyBuffer **proxy_buffer, void **out) +{ + if (!outer) outer = (IUnknown *)&proxy->proxy; + + proxy->proxy.IRpcProxyBuffer_iface.lpVtbl = &typelib_proxy_vtbl; + proxy->proxy.RefCount = 1; + proxy->proxy.pUnkOuter = outer; + + *proxy_buffer = &proxy->proxy.IRpcProxyBuffer_iface; + + return E_NOTIMPL; +} + +HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, IUnknown *outer, + REFIID iid, IRpcProxyBuffer **proxy_buffer, void **out) +{ + struct typelib_proxy *proxy; + HRESULT hr; + + TRACE("typeinfo %p, outer %p, iid %s, proxy %p, out %p.\n", + typeinfo, outer, debugstr_guid(iid), proxy_buffer, out); + + 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)) + heap_free(proxy); + + return hr; +}
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/cproxy.c | 21 --------------------- dlls/rpcrt4/ndr_typelib.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c index 7ca05e7248..6f15ed564d 100644 --- a/dlls/rpcrt4/cproxy.c +++ b/dlls/rpcrt4/cproxy.c @@ -512,24 +512,3 @@ HRESULT WINAPI NdrProxyErrorHandler(DWORD dwExceptionCode) else return HRESULT_FROM_WIN32(dwExceptionCode); } - -HRESULT WINAPI -CreateStubFromTypeInfo(ITypeInfo *pTypeInfo, REFIID riid, IUnknown *pUnkServer, - IRpcStubBuffer **ppStub ) -{ - typedef INT (WINAPI *MessageBoxA)(HWND,LPCSTR,LPCSTR,UINT); - HMODULE hUser32 = LoadLibraryA("user32"); - MessageBoxA pMessageBoxA = (void *)GetProcAddress(hUser32, "MessageBoxA"); - - FIXME("%p %s %p %p\n", pTypeInfo, debugstr_guid(riid), pUnkServer, ppStub); - if (pMessageBoxA) - { - pMessageBoxA(NULL, - "The native implementation of OLEAUT32.DLL cannot be used " - "with Wine's RPCRT4.DLL. Remove OLEAUT32.DLL and try again.\n", - "Wine: Unimplemented CreateProxyFromTypeInfo", - 0x10); - ExitProcess(1); - } - return E_NOTIMPL; -} diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 13075ac571..c0db6b78ff 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -91,3 +91,39 @@ HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, IUnknown *outer,
return hr; } + +struct typelib_stub +{ + CStdStubBuffer stub; +}; + +static HRESULT typelib_stub_init(struct typelib_stub *stub, IUnknown *server, + IRpcStubBuffer **stub_buffer) +{ + stub->stub.RefCount = 1; + *stub_buffer = (IRpcStubBuffer *)&stub->stub; + + return E_NOTIMPL; +} + +HRESULT WINAPI CreateStubFromTypeInfo(ITypeInfo *typeinfo, REFIID iid, + IUnknown *server, IRpcStubBuffer **stub_buffer) +{ + struct typelib_stub *stub; + HRESULT hr; + + TRACE("typeinfo %p, iid %s, server %p, stub_buffer %p.\n", + typeinfo, debugstr_guid(iid), server, stub_buffer); + + if (!(stub = heap_alloc_zero(sizeof(*stub)))) + { + ERR("Failed to allocate stub object.\n"); + return E_OUTOFMEMORY; + } + + hr = typelib_stub_init(stub, server, stub_buffer); + if (FAILED(hr)) + heap_free(stub); + + return hr; +}
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/cproxy.c | 2 +- dlls/rpcrt4/cpsf.h | 1 + dlls/rpcrt4/ndr_typelib.c | 112 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 110 insertions(+), 5 deletions(-)
diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c index 6f15ed564d..ab24b816a3 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 0ada0d16bb..c8980e526d 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 c0db6b78ff..25c4183ab4 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); + 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; }
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 73 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 25c4183ab4..aa54db20e0 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -199,35 +199,104 @@ HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, IUnknown *outer, struct typelib_stub { CStdStubBuffer stub; + IID iid; + MIDL_STUB_DESC stub_desc; + MIDL_SERVER_INFO server_info; + CInterfaceStubVtbl stub_vtbl; + unsigned short *offset_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); + + TRACE("(%p) decreasing refs to %d\n", stub, refcount); + + if (!refcount) + { + /* test_Release shows that native doesn't call Disconnect here. + We'll leave it in for the time being. */ + IRpcStubBuffer_Disconnect(iface); + + heap_free((void *)stub->stub_desc.pFormatTypes); + heap_free((void *)stub->server_info.ProcString); + heap_free(stub->offset_table); + heap_free(stub); + } + + return refcount; +} + static HRESULT typelib_stub_init(struct typelib_stub *stub, IUnknown *server, IRpcStubBuffer **stub_buffer) { + HRESULT hr; + + hr = IUnknown_QueryInterface(server, stub->stub_vtbl.header.piid, + (void **)&stub->stub.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; + IUnknown_AddRef(server); + } + + stub->stub.lpVtbl = &stub->stub_vtbl.Vtbl; stub->stub.RefCount = 1; - *stub_buffer = (IRpcStubBuffer *)&stub->stub;
- return E_NOTIMPL; + *stub_buffer = (IRpcStubBuffer *)&stub->stub; + return S_OK; }
HRESULT WINAPI CreateStubFromTypeInfo(ITypeInfo *typeinfo, REFIID iid, IUnknown *server, IRpcStubBuffer **stub_buffer) { struct typelib_stub *stub; + WORD funcs, parentfuncs; 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); + if (FAILED(hr)) + return hr; + if (!(stub = heap_alloc_zero(sizeof(*stub)))) { ERR("Failed to allocate stub object.\n"); return E_OUTOFMEMORY; }
+ init_stub_desc(&stub->stub_desc); + stub->server_info.pStubDesc = &stub->stub_desc; + + hr = build_format_strings(typeinfo, funcs, &stub->stub_desc.pFormatTypes, + &stub->server_info.ProcString, &stub->offset_table); + if (FAILED(hr)) + { + heap_free(stub); + return hr; + } + stub->server_info.FmtStringOffset = &stub->offset_table[-3]; + + stub->iid = *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; + stub->stub_vtbl.Vtbl.Release = typelib_stub_Release; + hr = typelib_stub_init(stub, server, stub_buffer); if (FAILED(hr)) + { + heap_free((void *)stub->stub_desc.pFormatTypes); + heap_free((void *)stub->server_info.ProcString); + heap_free(stub->offset_table); heap_free(stub); + }
return hr; }
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 180 +++++++++++++++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 1 deletion(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index aa54db20e0..51e198d711 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -22,6 +22,7 @@ #include "oaidl.h" #define USE_STUBLESS_PROXY #include "rpcproxy.h" +#include "ndrtypes.h" #include "wine/debug.h" #include "wine/heap.h"
@@ -29,11 +30,188 @@
WINE_DEFAULT_DEBUG_CHANNEL(ole);
+#define WRITE_CHAR(str, len, val) \ + do { if ((str)) (str)[(len)] = (val); (len)++; } while (0) +#define WRITE_SHORT(str, len, val) \ + do { if ((str)) *((short *)((str) + (len))) = (val); (len) += 2; } while (0) + +static unsigned int type_memsize(ITypeInfo *typeinfo, TYPEDESC *desc) +{ + switch (desc->vt) + { + case VT_I1: + case VT_UI1: + return 1; + case VT_I2: + case VT_UI2: + case VT_BOOL: + return 2; + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_HRESULT: + return 4; + case VT_I8: + case VT_UI8: + case VT_R8: + case VT_DATE: + return 8; + case VT_BSTR: + case VT_SAFEARRAY: + case VT_PTR: + case VT_UNKNOWN: + case VT_DISPATCH: + return sizeof(void *); + case VT_VARIANT: + return sizeof(VARIANT); + case VT_CARRAY: + { + unsigned int size = type_memsize(typeinfo, &desc->lpadesc->tdescElem); + unsigned int i; + for (i = 0; i < desc->lpadesc->cDims; i++) + size *= desc->lpadesc->rgbounds[i].cElements; + return size; + } + case VT_USERDEFINED: + { + unsigned int size = 0; + ITypeInfo *refinfo; + TYPEATTR *attr; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + size = attr->cbSizeInstance; + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + return size; + } + default: + FIXME("unhandled type %u\n", desc->vt); + return 0; + } +} + +static unsigned short get_stack_size(ITypeInfo *typeinfo, TYPEDESC *desc) +{ +#ifdef __i386__ + if (desc->vt == VT_CARRAY) + return sizeof(void *); + return (type_memsize(typeinfo, desc) + 3) & ~3; +#elif defined(__x86_64__) + return sizeof(void *); +#else +#warn get_stack_size() not implemented for this architecture +#endif +} + +static HRESULT write_param_fs(ITypeInfo *typeinfo, unsigned char *type, + size_t *typelen, unsigned char *proc, size_t *proclen, ELEMDESC *desc, + BOOL is_return, unsigned short *stack_offset) +{ + return E_NOTIMPL; +} + +static void write_proc_func_header(ITypeInfo *typeinfo, FUNCDESC *desc, + WORD proc_idx, unsigned char *proc, size_t *proclen) +{ + unsigned short stack_size = 2 * sizeof(void *); /* This + return */ + WORD param_idx; + + WRITE_CHAR (proc, *proclen, FC_AUTO_HANDLE); + WRITE_CHAR (proc, *proclen, Oi_OBJECT_PROC | Oi_OBJ_USE_V2_INTERPRETER); + WRITE_SHORT(proc, *proclen, proc_idx); + for (param_idx = 0; param_idx < desc->cParams; param_idx++) + stack_size += get_stack_size(typeinfo, &desc->lprgelemdescParam[param_idx].tdesc); + WRITE_SHORT(proc, *proclen, stack_size); + + WRITE_SHORT(proc, *proclen, 0); /* constant_client_buffer_size */ + WRITE_SHORT(proc, *proclen, 0); /* constant_server_buffer_size */ + WRITE_CHAR (proc, *proclen, 0x07); /* HasReturn | ClientMustSize | ServerMustSize */ + WRITE_CHAR (proc, *proclen, desc->cParams + 1); /* incl. return value */ +} + +static HRESULT write_iface_fs(ITypeInfo *typeinfo, WORD funcs, + unsigned char *type, size_t *typelen, unsigned char *proc, + size_t *proclen, unsigned short *offset) +{ + unsigned short stack_offset; + WORD proc_idx, param_idx; + FUNCDESC *desc; + HRESULT hr; + + for (proc_idx = 0; proc_idx < funcs; proc_idx++) + { + TRACE("proc %d\n", proc_idx); + + hr = ITypeInfo_GetFuncDesc(typeinfo, proc_idx, &desc); + if (FAILED(hr)) return hr; + + if (offset) + offset[proc_idx] = *proclen; + + write_proc_func_header(typeinfo, desc, proc_idx + 3, proc, proclen); + + stack_offset = sizeof(void *); /* This */ + for (param_idx = 0; param_idx < desc->cParams; param_idx++) + { + TRACE("param %d\n", param_idx); + hr = write_param_fs(typeinfo, type, typelen, proc, proclen, + &desc->lprgelemdescParam[param_idx], FALSE, &stack_offset); + if (FAILED(hr)) return hr; + } + + hr = write_param_fs(typeinfo, type, typelen, proc, proclen, + &desc->elemdescFunc, TRUE, &stack_offset); + if (FAILED(hr)) return hr; + + ITypeInfo_ReleaseFuncDesc(typeinfo, desc); + } + + return S_OK; +} + 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; + size_t typelen = 0, proclen = 0; + unsigned char *type, *proc; + unsigned short *offset; + HRESULT hr; + + hr = write_iface_fs(typeinfo, funcs, NULL, &typelen, NULL, &proclen, NULL); + if (FAILED(hr)) return hr; + + type = heap_alloc(typelen); + proc = heap_alloc(proclen); + offset = heap_alloc(funcs * sizeof(*offset)); + if (!type || !proc || !offset) + { + ERR("Failed to allocate format strings.\n"); + hr = E_OUTOFMEMORY; + goto err; + } + + typelen = 0; + proclen = 0; + + hr = write_iface_fs(typeinfo, funcs, type, &typelen, proc, &proclen, offset); + if (SUCCEEDED(hr)) + { + *type_ret = type; + *proc_ret = proc; + *offset_ret = offset; + return S_OK; + } + +err: + heap_free(type); + heap_free(proc); + heap_free(offset); + return hr; }
/* Common helper for Create{Proxy,Stub}FromTypeInfo(). */
On Sat, Nov 03, 2018 at 06:07:17PM -0500, Zebediah Figura wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
dlls/rpcrt4/ndr_typelib.c | 180 +++++++++++++++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 1 deletion(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index aa54db20e0..51e198d711 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -22,6 +22,7 @@ +static HRESULT write_iface_fs(ITypeInfo *typeinfo, WORD funcs,
unsigned char *type, size_t *typelen, unsigned char *proc,
size_t *proclen, unsigned short *offset)
+{
- unsigned short stack_offset;
- WORD proc_idx, param_idx;
- FUNCDESC *desc;
- HRESULT hr;
- for (proc_idx = 0; proc_idx < funcs; proc_idx++)
- {
TRACE("proc %d\n", proc_idx);
hr = ITypeInfo_GetFuncDesc(typeinfo, proc_idx, &desc);
if (FAILED(hr)) return hr;
if (offset)
offset[proc_idx] = *proclen;
write_proc_func_header(typeinfo, desc, proc_idx + 3, proc, proclen);
stack_offset = sizeof(void *); /* This */
for (param_idx = 0; param_idx < desc->cParams; param_idx++)
{
TRACE("param %d\n", param_idx);
hr = write_param_fs(typeinfo, type, typelen, proc, proclen,
&desc->lprgelemdescParam[param_idx], FALSE, &stack_offset);
if (FAILED(hr)) return hr;
You leak desc in the failure case here.
}
hr = write_param_fs(typeinfo, type, typelen, proc, proclen,
&desc->elemdescFunc, TRUE, &stack_offset);
if (FAILED(hr)) return hr;
Also here.
ITypeInfo_ReleaseFuncDesc(typeinfo, desc);
- }
- return S_OK;
+}
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 256 +++++++++++++++++++++++++++++++++++++- 1 file changed, 255 insertions(+), 1 deletion(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 51e198d711..ee4e551fcb 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -35,6 +35,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); #define WRITE_SHORT(str, len, val) \ do { if ((str)) *((short *)((str) + (len))) = (val); (len) += 2; } while (0)
+static unsigned char get_base_type(VARTYPE vt) +{ + switch (vt) + { + case VT_I1: return FC_SMALL; + case VT_BOOL: + case VT_I2: return FC_SHORT; + case VT_INT: + case VT_ERROR: + case VT_HRESULT: + case VT_I4: return FC_LONG; + case VT_I8: + case VT_UI8: return FC_HYPER; + case VT_UI1: return FC_USMALL; + case VT_UI2: return FC_USHORT; + case VT_UINT: + case VT_UI4: return FC_ULONG; + case VT_R4: return FC_FLOAT; + case VT_DATE: + case VT_R8: return FC_DOUBLE; + default: return 0; + } +} + static unsigned int type_memsize(ITypeInfo *typeinfo, TYPEDESC *desc) { switch (desc->vt) @@ -94,6 +118,12 @@ static unsigned int type_memsize(ITypeInfo *typeinfo, TYPEDESC *desc) } }
+static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEDESC *desc, BOOL toplevel, BOOL onstack) +{ + return E_NOTIMPL; +} + static unsigned short get_stack_size(ITypeInfo *typeinfo, TYPEDESC *desc) { #ifdef __i386__ @@ -107,11 +137,235 @@ static unsigned short get_stack_size(ITypeInfo *typeinfo, TYPEDESC *desc) #endif }
+static const unsigned short MustSize = 0x0001; +static const unsigned short MustFree = 0x0002; +static const unsigned short IsIn = 0x0008; +static const unsigned short IsOut = 0x0010; +static const unsigned short IsReturn = 0x0020; +static const unsigned short IsBasetype = 0x0040; +static const unsigned short IsByValue = 0x0080; +static const unsigned short IsSimpleRef = 0x0100; + +static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in, + int is_out, unsigned short *server_size, unsigned short *flags, + unsigned char *basetype, TYPEDESC **tfs_tdesc) +{ + ITypeInfo *refinfo; + TYPEATTR *attr; + HRESULT hr; + + switch (tdesc->vt) + { + case VT_UNKNOWN: + case VT_DISPATCH: + *flags |= MustFree; + if (is_in && is_out) + *server_size = sizeof(void *); + break; + case VT_PTR: + *flags |= MustFree; + + if (tdesc->lptdesc->vt == VT_USERDEFINED) + { + ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->lptdesc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + switch (attr->typekind) + { + case TKIND_INTERFACE: + case TKIND_DISPATCH: + case TKIND_COCLASS: + if (is_in && is_out) + *server_size = sizeof(void *); + break; + default: + *server_size = sizeof(void *); + } + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + } + else + *server_size = sizeof(void *); + break; + case VT_CARRAY: + *flags |= IsSimpleRef | MustFree; + *server_size = type_memsize(typeinfo, tdesc); + *tfs_tdesc = tdesc; + break; + case VT_USERDEFINED: + ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + switch (attr->typekind) + { + case TKIND_ENUM: + *flags |= IsSimpleRef | IsBasetype; + if (!is_in && is_out) + *server_size = sizeof(void *); + *basetype = FC_ENUM32; + break; + case TKIND_RECORD: + *flags |= IsSimpleRef | MustFree; + if (!is_in && is_out) + *server_size = attr->cbSizeInstance; + *tfs_tdesc = tdesc; + break; + case TKIND_INTERFACE: + case TKIND_DISPATCH: + case TKIND_COCLASS: + *flags |= MustFree; + break; + case TKIND_ALIAS: + hr = get_param_pointer_info(refinfo, &attr->tdescAlias, is_in, + is_out, server_size, flags, basetype, tfs_tdesc); + if (FAILED(hr)) + return hr; + break; + default: + FIXME("unhandled kind %#x\n", attr->typekind); + return E_NOTIMPL; + } + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + break; + default: + *flags |= IsSimpleRef; + *tfs_tdesc = tdesc; + if (!is_in && is_out) + *server_size = type_memsize(typeinfo, tdesc); + if ((*basetype = get_base_type(tdesc->vt))) + *flags |= IsBasetype; + break; + } + + return S_OK; +} + +static HRESULT get_param_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in, + int is_out, unsigned short *server_size, unsigned short *flags, + unsigned char *basetype, TYPEDESC **tfs_tdesc) +{ + ITypeInfo *refinfo; + TYPEATTR *attr; + HRESULT hr; + + *server_size = 0; + *flags = MustSize; + *basetype = 0; + *tfs_tdesc = tdesc; + + TRACE("vt %u\n", tdesc->vt); + + switch (tdesc->vt) + { + case VT_VARIANT: +#ifndef __i386__ + *flags |= IsSimpleRef | MustFree; + break; +#endif + /* otherwise fall through */ + case VT_BSTR: + case VT_SAFEARRAY: + case VT_CY: + *flags |= IsByValue | MustFree; + break; + case VT_UNKNOWN: + case VT_DISPATCH: + case VT_CARRAY: + *flags |= MustFree; + break; + case VT_PTR: + return get_param_pointer_info(typeinfo, tdesc->lptdesc, is_in, is_out, + server_size, flags, basetype, tfs_tdesc); + case VT_USERDEFINED: + ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + switch (attr->typekind) + { + case TKIND_ENUM: + *flags |= IsBasetype; + *basetype = FC_ENUM32; + break; + case TKIND_RECORD: +#ifdef __i386__ + *flags |= IsByValue | MustFree; +#elif defined(__x86_64__) + if (attr->cbSizeInstance <= 8) + *flags |= IsByValue | MustFree; + else + *flags |= IsSimpleRef | MustFree; +#endif + break; + case TKIND_ALIAS: + hr = get_param_info(refinfo, &attr->tdescAlias, is_in, is_out, + server_size, flags, basetype, tfs_tdesc); + if (FAILED(hr)) + return hr; + break; + default: + FIXME("unhandled kind %#x\n", attr->typekind); + return E_NOTIMPL; + } + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + break; + default: + if ((*basetype = get_base_type(tdesc->vt))) + *flags |= IsBasetype; + else + { + FIXME("unhandled type %u\n", tdesc->vt); + return E_NOTIMPL; + } + break; + } + + return S_OK; +} + static HRESULT write_param_fs(ITypeInfo *typeinfo, unsigned char *type, size_t *typelen, unsigned char *proc, size_t *proclen, ELEMDESC *desc, BOOL is_return, unsigned short *stack_offset) { - return E_NOTIMPL; + USHORT param_flags = desc->paramdesc.wParamFlags; + int is_in = param_flags & PARAMFLAG_FIN; + int is_out = param_flags & PARAMFLAG_FOUT; + TYPEDESC *tdesc = &desc->tdesc, *tfs_tdesc; + unsigned short server_size; + unsigned short stack_size = get_stack_size(typeinfo, tdesc); + unsigned char basetype; + unsigned short flags; + size_t off = 0; + HRESULT hr; + + hr = get_param_info(typeinfo, tdesc, is_in, is_out, &server_size, &flags, + &basetype, &tfs_tdesc); + + if (is_in) flags |= IsIn; + if (is_out) flags |= IsOut; + if (is_return) flags |= IsOut | IsReturn; + + server_size = (server_size + 7) / 8; + if (server_size >= 8) server_size = 0; + flags |= server_size << 13; + + if (!basetype) + off = write_type_tfs(typeinfo, type, typelen, tfs_tdesc, TRUE, server_size != 0); + + if (SUCCEEDED(hr)) + { + WRITE_SHORT(proc, *proclen, flags); + WRITE_SHORT(proc, *proclen, *stack_offset); + WRITE_SHORT(proc, *proclen, basetype ? basetype : off); + + *stack_offset += stack_size; + } + + return hr; }
static void write_proc_func_header(ITypeInfo *typeinfo, FUNCDESC *desc,
On Sat, Nov 03, 2018 at 06:07:18PM -0500, Zebediah Figura wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
dlls/rpcrt4/ndr_typelib.c | 256 +++++++++++++++++++++++++++++++++++++- 1 file changed, 255 insertions(+), 1 deletion(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 51e198d711..ee4e551fcb 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -35,6 +35,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
+static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in,
int is_out, unsigned short *server_size, unsigned short *flags,
unsigned char *basetype, TYPEDESC **tfs_tdesc)
+{
- ITypeInfo *refinfo;
- TYPEATTR *attr;
- HRESULT hr;
- switch (tdesc->vt)
- {
- case VT_UNKNOWN:
- case VT_DISPATCH:
*flags |= MustFree;
if (is_in && is_out)
*server_size = sizeof(void *);
break;
- case VT_PTR:
*flags |= MustFree;
if (tdesc->lptdesc->vt == VT_USERDEFINED)
{
ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->lptdesc->hreftype, &refinfo);
ITypeInfo_GetTypeAttr(refinfo, &attr);
switch (attr->typekind)
{
case TKIND_INTERFACE:
case TKIND_DISPATCH:
case TKIND_COCLASS:
if (is_in && is_out)
*server_size = sizeof(void *);
break;
default:
*server_size = sizeof(void *);
}
ITypeInfo_ReleaseTypeAttr(refinfo, attr);
ITypeInfo_Release(refinfo);
}
else
*server_size = sizeof(void *);
break;
- case VT_CARRAY:
*flags |= IsSimpleRef | MustFree;
*server_size = type_memsize(typeinfo, tdesc);
*tfs_tdesc = tdesc;
break;
- case VT_USERDEFINED:
ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo);
ITypeInfo_GetTypeAttr(refinfo, &attr);
switch (attr->typekind)
{
case TKIND_ENUM:
*flags |= IsSimpleRef | IsBasetype;
if (!is_in && is_out)
*server_size = sizeof(void *);
*basetype = FC_ENUM32;
break;
case TKIND_RECORD:
*flags |= IsSimpleRef | MustFree;
if (!is_in && is_out)
*server_size = attr->cbSizeInstance;
*tfs_tdesc = tdesc;
break;
case TKIND_INTERFACE:
case TKIND_DISPATCH:
case TKIND_COCLASS:
*flags |= MustFree;
break;
case TKIND_ALIAS:
hr = get_param_pointer_info(refinfo, &attr->tdescAlias, is_in,
is_out, server_size, flags, basetype, tfs_tdesc);
if (FAILED(hr))
return hr;
Leaking refinfo and attr.
break;
default:
FIXME("unhandled kind %#x\n", attr->typekind);
return E_NOTIMPL;
And here.
}
ITypeInfo_ReleaseTypeAttr(refinfo, attr);
ITypeInfo_Release(refinfo);
break;
- default:
*flags |= IsSimpleRef;
*tfs_tdesc = tdesc;
if (!is_in && is_out)
*server_size = type_memsize(typeinfo, tdesc);
if ((*basetype = get_base_type(tdesc->vt)))
*flags |= IsBasetype;
break;
- }
- return S_OK;
+}
+static HRESULT get_param_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in,
int is_out, unsigned short *server_size, unsigned short *flags,
unsigned char *basetype, TYPEDESC **tfs_tdesc)
+{
- ITypeInfo *refinfo;
- TYPEATTR *attr;
- HRESULT hr;
- *server_size = 0;
- *flags = MustSize;
- *basetype = 0;
- *tfs_tdesc = tdesc;
- TRACE("vt %u\n", tdesc->vt);
- switch (tdesc->vt)
- {
- case VT_VARIANT:
+#ifndef __i386__
*flags |= IsSimpleRef | MustFree;
break;
+#endif
/* otherwise fall through */
- case VT_BSTR:
- case VT_SAFEARRAY:
- case VT_CY:
*flags |= IsByValue | MustFree;
break;
- case VT_UNKNOWN:
- case VT_DISPATCH:
- case VT_CARRAY:
*flags |= MustFree;
break;
- case VT_PTR:
return get_param_pointer_info(typeinfo, tdesc->lptdesc, is_in, is_out,
server_size, flags, basetype, tfs_tdesc);
- case VT_USERDEFINED:
ITypeInfo_GetRefTypeInfo(typeinfo, tdesc->hreftype, &refinfo);
ITypeInfo_GetTypeAttr(refinfo, &attr);
switch (attr->typekind)
{
case TKIND_ENUM:
*flags |= IsBasetype;
*basetype = FC_ENUM32;
break;
case TKIND_RECORD:
+#ifdef __i386__
*flags |= IsByValue | MustFree;
+#elif defined(__x86_64__)
if (attr->cbSizeInstance <= 8)
*flags |= IsByValue | MustFree;
else
*flags |= IsSimpleRef | MustFree;
+#endif
break;
case TKIND_ALIAS:
hr = get_param_info(refinfo, &attr->tdescAlias, is_in, is_out,
server_size, flags, basetype, tfs_tdesc);
if (FAILED(hr))
return hr;
And here.
break;
default:
FIXME("unhandled kind %#x\n", attr->typekind);
return E_NOTIMPL;
And here.
}
ITypeInfo_ReleaseTypeAttr(refinfo, attr);
ITypeInfo_Release(refinfo);
break;
- default:
if ((*basetype = get_base_type(tdesc->vt)))
*flags |= IsBasetype;
else
{
FIXME("unhandled type %u\n", tdesc->vt);
return E_NOTIMPL;
}
break;
- }
- return S_OK;
+}
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 103 +++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index ee4e551fcb..46e0787bd7 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <assert.h> + #define COBJMACROS #include "oaidl.h" #define USE_STUBLESS_PROXY @@ -30,6 +32,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(ole);
+static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEDESC *desc, BOOL toplevel, BOOL onstack); + #define WRITE_CHAR(str, len, val) \ do { if ((str)) (str)[(len)] = (val); (len)++; } while (0) #define WRITE_SHORT(str, len, val) \ @@ -118,10 +123,106 @@ static unsigned int type_memsize(ITypeInfo *typeinfo, TYPEDESC *desc) } }
+static size_t write_ip_tfs(unsigned char *str, size_t *len, const GUID *iid) +{ + size_t off = *len; + + if (str) + { + str[*len] = FC_IP; + str[*len+1] = FC_CONSTANT_IID; + memcpy(str + *len + 2, iid, sizeof(*iid)); + } + *len += 2 + sizeof(*iid); + + return off; +} + +static size_t write_pointer_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEDESC *desc, BOOL toplevel, BOOL onstack) +{ + unsigned char basetype, flags = 0; + size_t ref, off = *len; + ITypeInfo *refinfo; + TYPEATTR *attr; + + if (desc->vt == VT_USERDEFINED) + { + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + switch (attr->typekind) + { + case TKIND_ENUM: + assert(!toplevel); /* toplevel base-type pointers should use IsSimpleRef */ + WRITE_CHAR(str, *len, FC_UP); + WRITE_CHAR(str, *len, FC_SIMPLE_POINTER); + WRITE_CHAR(str, *len, FC_ENUM32); + WRITE_CHAR(str, *len, FC_PAD); + break; + case TKIND_INTERFACE: + case TKIND_DISPATCH: + write_ip_tfs(str, len, &attr->guid); + break; + case TKIND_ALIAS: + off = write_pointer_tfs(refinfo, str, len, &attr->tdescAlias, toplevel, onstack); + break; + default: + FIXME("unhandled kind %#x\n", attr->typekind); + WRITE_SHORT(str, *len, 0); + break; + } + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + } + else if ((basetype = get_base_type(desc->vt))) + { + assert(!toplevel); /* toplevel base-type pointers should use IsSimpleRef */ + WRITE_CHAR(str, *len, FC_UP); + WRITE_CHAR(str, *len, FC_SIMPLE_POINTER); + WRITE_CHAR(str, *len, basetype); + WRITE_CHAR(str, *len, FC_PAD); + } + else + { + ref = write_type_tfs(typeinfo, str, len, desc, FALSE, FALSE); + + if (onstack) flags |= FC_ALLOCED_ON_STACK; + if (desc->vt == VT_PTR || desc->vt == VT_UNKNOWN || desc->vt == VT_DISPATCH) + flags |= FC_POINTER_DEREF; + + off = *len; + + WRITE_CHAR (str, *len, toplevel ? FC_RP : FC_UP); + WRITE_CHAR (str, *len, flags); + WRITE_SHORT(str, *len, ref - *len); + } + + return off; +} + static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, size_t *len, TYPEDESC *desc, BOOL toplevel, BOOL onstack) { - return E_NOTIMPL; + size_t off; + + TRACE("vt %d%s\n", desc->vt, toplevel ? " (toplevel)" : ""); + + switch (desc->vt) + { + case VT_PTR: + return write_pointer_tfs(typeinfo, str, len, desc->lptdesc, toplevel, onstack); + default: + /* base types are always embedded directly */ + assert(!get_base_type(desc->vt)); + FIXME("unhandled type %u\n", desc->vt); + off = *len; + WRITE_SHORT(str, *len, 0); + break; + } + + return off; }
static unsigned short get_stack_size(ITypeInfo *typeinfo, TYPEDESC *desc)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 106 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 46e0787bd7..4b7153e4d0 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -39,6 +39,8 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, do { if ((str)) (str)[(len)] = (val); (len)++; } while (0) #define WRITE_SHORT(str, len, val) \ do { if ((str)) *((short *)((str) + (len))) = (val); (len) += 2; } while (0) +#define WRITE_INT(str, len, val) \ + do { if ((str)) *((int *)((str) + (len))) = (val); (len) += 4; } while (0)
static unsigned char get_base_type(VARTYPE vt) { @@ -123,6 +125,108 @@ static unsigned int type_memsize(ITypeInfo *typeinfo, TYPEDESC *desc) } }
+static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc); + +static unsigned char get_struct_fc(ITypeInfo *typeinfo, TYPEATTR *attr) +{ + unsigned char fc = FC_STRUCT; + VARDESC *desc; + VARTYPE vt; + WORD i; + + for (i = 0; i < attr->cVars; i++) + { + ITypeInfo_GetVarDesc(typeinfo, i, &desc); + vt = desc->elemdescVar.tdesc.vt; + + switch (vt) + { + case VT_CARRAY: + if (get_array_fc(typeinfo, &desc->elemdescVar.tdesc.lpadesc->tdescElem) == FC_BOGUS_ARRAY) + fc = FC_BOGUS_STRUCT; + break; + default: + if (!get_base_type(vt)) + { + FIXME("unhandled type %u\n", vt); + fc = FC_BOGUS_STRUCT; + } + break; + } + + ITypeInfo_ReleaseVarDesc(typeinfo, desc); + } + + return fc; +} + +static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc) +{ + if (get_base_type(desc->vt)) + return FC_LGFARRAY; + else if (desc->vt == VT_USERDEFINED) + { + ITypeInfo *refinfo; + TYPEATTR *attr; + unsigned char fc; + + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + if (attr->typekind == TKIND_ENUM) + fc = FC_LGFARRAY; + else if (attr->typekind == TKIND_RECORD && get_struct_fc(refinfo, attr) == FC_STRUCT) + fc = FC_LGFARRAY; + else + fc = FC_BOGUS_ARRAY; + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + + return fc; + } + else + return FC_BOGUS_ARRAY; +} + +static size_t write_array_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, ARRAYDESC *desc) +{ + unsigned char fc = get_array_fc(typeinfo, &desc->tdescElem); + ULONG size = type_memsize(typeinfo, &desc->tdescElem); + unsigned char basetype; + size_t ref = 0, off; + USHORT i; + + if (fc != FC_LGFARRAY) + FIXME("complex arrays not implemented\n"); + + if (!(basetype = get_base_type(desc->tdescElem.vt))) + ref = write_type_tfs(typeinfo, str, len, &desc->tdescElem, FALSE, FALSE); + + /* In theory arrays should be nested, but there's no reason not to marshal + * [x][y] as [x*y]. */ + for (i = 0; i < desc->cDims; i++) size *= desc->rgbounds[i].cElements; + + off = *len; + + WRITE_CHAR(str, *len, FC_LGFARRAY); + WRITE_CHAR(str, *len, 0); + WRITE_INT (str, *len, size); + if (basetype) + WRITE_CHAR(str, *len, basetype); + else + { + WRITE_CHAR (str, *len, FC_EMBEDDED_COMPLEX); + WRITE_CHAR (str, *len, 0); + WRITE_SHORT(str, *len, ref - *len); + WRITE_CHAR (str, *len, FC_PAD); + } + WRITE_CHAR(str, *len, FC_END); + + return off; +} + static size_t write_ip_tfs(unsigned char *str, size_t *len, const GUID *iid) { size_t off = *len; @@ -213,6 +317,8 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, { case VT_PTR: return write_pointer_tfs(typeinfo, str, len, desc->lptdesc, toplevel, onstack); + case VT_CARRAY: + return write_array_tfs(typeinfo, str, len, desc->lpadesc); default: /* base types are always embedded directly */ assert(!get_base_type(desc->vt));
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 4b7153e4d0..f78dd85b8a 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -189,6 +189,24 @@ static unsigned char get_array_fc(ITypeInfo *typeinfo, TYPEDESC *desc) return FC_BOGUS_ARRAY; }
+static size_t write_struct_tfs(ITypeInfo *typeinfo, unsigned char *str, + size_t *len, TYPEATTR *attr) +{ + unsigned char fc = get_struct_fc(typeinfo, attr); + size_t off = *len; + + if (fc != FC_STRUCT) + FIXME("fc %02x not implemented\n", fc); + + WRITE_CHAR (str, *len, FC_STRUCT); + WRITE_CHAR (str, *len, attr->cbAlignment - 1); + WRITE_SHORT(str, *len, attr->cbSizeInstance); + WRITE_CHAR (str, *len, FC_PAD); + WRITE_CHAR (str, *len, FC_END); + + return off; +} + static size_t write_array_tfs(ITypeInfo *typeinfo, unsigned char *str, size_t *len, ARRAYDESC *desc) { @@ -264,6 +282,14 @@ static size_t write_pointer_tfs(ITypeInfo *typeinfo, unsigned char *str, WRITE_CHAR(str, *len, FC_ENUM32); WRITE_CHAR(str, *len, FC_PAD); break; + case TKIND_RECORD: + assert(!toplevel); /* toplevel struct pointers should use IsSimpleRef */ + ref = write_struct_tfs(refinfo, str, len, attr); + off = *len; + WRITE_CHAR (str, *len, FC_UP); + WRITE_CHAR (str, *len, 0); + WRITE_SHORT(str, *len, ref - *len); + break; case TKIND_INTERFACE: case TKIND_DISPATCH: write_ip_tfs(str, len, &attr->guid); @@ -309,6 +335,8 @@ static size_t write_pointer_tfs(ITypeInfo *typeinfo, unsigned char *str, static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, size_t *len, TYPEDESC *desc, BOOL toplevel, BOOL onstack) { + ITypeInfo *refinfo; + TYPEATTR *attr; size_t off;
TRACE("vt %d%s\n", desc->vt, toplevel ? " (toplevel)" : ""); @@ -319,6 +347,25 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, return write_pointer_tfs(typeinfo, str, len, desc->lptdesc, toplevel, onstack); case VT_CARRAY: return write_array_tfs(typeinfo, str, len, desc->lpadesc); + case VT_USERDEFINED: + ITypeInfo_GetRefTypeInfo(typeinfo, desc->hreftype, &refinfo); + ITypeInfo_GetTypeAttr(refinfo, &attr); + + switch (attr->typekind) + { + case TKIND_RECORD: + off = write_struct_tfs(refinfo, str, len, attr); + break; + default: + FIXME("unhandled kind %u\n", attr->typekind); + off = *len; + WRITE_SHORT(str, *len, 0); + break; + } + + ITypeInfo_ReleaseTypeAttr(refinfo, attr); + ITypeInfo_Release(refinfo); + break; default: /* base types are always embedded directly */ assert(!get_base_type(desc->vt));
Signed-off-by: Zebediah Figura z.figura12@gmail.com ---
Automation types (BSTR, VARIANT, LPSAFEARRAY) are user-marshalled, which means that they require long format strings to represent the wire form of the data. Ideally this should be generated by widl at build time. However, we can't just create a dummy idl and retrieve the type format string from the generated proxy file, since we have no way of retrieving the length of the type format string (and we do need a way of copying it, since it must be contiguous with ours). Instead the solution I propose is to use a script to parse the type format string (and the other parts that we need) into a generated file, to be done at build time. Since we need widl to do this, and since it can be done very easily in shell script, I have embedded it as a Makefile rule.
Makefile.in | 1 + dlls/rpcrt4/Makefile.in | 21 ++++++++++++++++++++- dlls/rpcrt4/ndr_typelib.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/Makefile.in b/Makefile.in index c1242afc01..25f535dc7f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -76,6 +76,7 @@ SUBDIRS = @SUBDIRS@ RUNTESTFLAGS = -q -P wine MAKEDEP = $(TOOLSDIR)/tools/makedep$(TOOLSEXT) WRC = $(TOOLSDIR)/tools/wrc/wrc$(TOOLSEXT) +WIDL = $(TOOLSDIR)/tools/widl/widl$(TOOLSEXT) PACKAGE_VERSION = @PACKAGE_VERSION@ SED_CMD = LC_ALL=C sed -e 's,@bindir@,$(bindir),g' -e 's,@dlldir@,$(dlldir),g' -e 's,@srcdir@,$(srcdir),g' -e 's,@PACKAGE_STRING@,@PACKAGE_STRING@,g' -e 's,@PACKAGE_VERSION@,@PACKAGE_VERSION@,g' LDRPATH_INSTALL = @LDRPATH_INSTALL@ diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in index ad67edf92e..aa80c2e7c7 100644 --- a/dlls/rpcrt4/Makefile.in +++ b/dlls/rpcrt4/Makefile.in @@ -2,7 +2,7 @@ EXTRADEFS = -D_RPCRT4_ -DMSWMSG MODULE = rpcrt4.dll IMPORTLIB = rpcrt4 IMPORTS = uuid advapi32 -DELAYIMPORTS = iphlpapi wininet secur32 user32 ws2_32 +DELAYIMPORTS = iphlpapi wininet secur32 user32 ws2_32 oleaut32
C_SRCS = \ cproxy.c \ @@ -28,3 +28,22 @@ C_SRCS = \ RC_SRCS = version.rc
IDL_SRCS = epm.idl + +EXTRA_OBJS = ndr_typelib_generated.o + +ndr_typelib_generated.c: $(WIDL) + echo > ndr_typelib_generated.c '/* Automatically generated from Makefile.in, do not edit */' && \ + echo >> ndr_typelib_generated.c '#include "oaidl.h"' && \ + echo >> ndr_typelib_generated.c '#include "rpcproxy.h"' && \ + echo > ndr_typelib_generated.idl 'import "oaidl.idl"; [object] interface dummy {void dummy(BSTR a, IUnknown *b, IDispatch *c, VARIANT d, LPSAFEARRAY e); }' && \ + $(WIDL) $(WIDLFLAGS) -I $(top_srcdir)/include -p -o ndr_typelib_generated_p.c ndr_typelib_generated.idl && \ + echo >> ndr_typelib_generated.c 'const unsigned char oleaut_tfs[] = {' && \ + awk '/__MIDL_TypeFormatString =/,/};/' ndr_typelib_generated_p.c | head -n -2 | tail -n +5 >> ndr_typelib_generated.c && \ + echo >> ndr_typelib_generated.c '};' && \ + sed -n -e 's/#define TYPE_FORMAT_STRING_SIZE ([0-9]+)/const size_t oleaut_tfs_size = \1;/p' ndr_typelib_generated_p.c >> ndr_typelib_generated.c && \ + echo >> ndr_typelib_generated.c 'const unsigned short oleaut_offsets[] = {' && \ + sed -n -e 's/.*&__MIDL_TypeFormatString.Format[([0-9]+)].*/ \1,/p' ndr_typelib_generated_p.c | head -n 5 >> ndr_typelib_generated.c && \ + echo >> ndr_typelib_generated.c '};' && \ + echo >> ndr_typelib_generated.c 'const USER_MARSHAL_ROUTINE_QUADRUPLE oleaut_user_marshal[] = ' && \ + awk '/UserMarshalRoutines[] =/,/};/' ndr_typelib_generated_p.c | tail -n +2 >> ndr_typelib_generated.c && \ + rm ndr_typelib_generated_p.c ndr_typelib_generated.idl diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index f78dd85b8a..687db1a5fa 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -42,6 +42,25 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, #define WRITE_INT(str, len, val) \ do { if ((str)) *((int *)((str) + (len))) = (val); (len) += 4; } while (0)
+extern const unsigned char oleaut_tfs[]; +extern const size_t oleaut_tfs_size; +extern const unsigned short oleaut_offsets[5]; +extern const USER_MARSHAL_ROUTINE_QUADRUPLE oleaut_user_marshal[]; + +static unsigned short write_oleaut_tfs(VARTYPE vt) +{ + switch (vt) + { + case VT_BSTR: return oleaut_offsets[0]; + case VT_UNKNOWN: return oleaut_offsets[1]; + case VT_DISPATCH: return oleaut_offsets[2]; + case VT_VARIANT: return oleaut_offsets[3]; + case VT_SAFEARRAY: return oleaut_offsets[4]; + } + + return 0; +} + static unsigned char get_base_type(VARTYPE vt) { switch (vt) @@ -341,6 +360,9 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str,
TRACE("vt %d%s\n", desc->vt, toplevel ? " (toplevel)" : "");
+ if ((off = write_oleaut_tfs(desc->vt))) + return off; + switch (desc->vt) { case VT_PTR: @@ -685,7 +707,7 @@ static HRESULT build_format_strings(ITypeInfo *typeinfo, WORD funcs, const unsigned char **type_ret, const unsigned char **proc_ret, unsigned short **offset_ret) { - size_t typelen = 0, proclen = 0; + size_t typelen = oleaut_tfs_size, proclen = 0; unsigned char *type, *proc; unsigned short *offset; HRESULT hr; @@ -703,7 +725,8 @@ static HRESULT build_format_strings(ITypeInfo *typeinfo, WORD funcs, goto err; }
- typelen = 0; + memcpy(type, oleaut_tfs, oleaut_tfs_size); + typelen = oleaut_tfs_size; proclen = 0;
hr = write_iface_fs(typeinfo, funcs, type, &typelen, proc, &proclen, offset); @@ -760,6 +783,7 @@ static void init_stub_desc(MIDL_STUB_DESC *desc) desc->pfnAllocate = NdrOleAllocate; desc->pfnFree = NdrOleFree; desc->Version = 0x50002; + desc->aUserMarshalQuadruple = oleaut_user_marshal; /* type format string is initialized with proc format string and offset table */ }
On Sat, Nov 03, 2018 at 06:07:22PM -0500, Zebediah Figura wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
Automation types (BSTR, VARIANT, LPSAFEARRAY) are user-marshalled, which means that they require long format strings to represent the wire form of the data. Ideally this should be generated by widl at build time. However, we can't just create a dummy idl and retrieve the type format string from the generated proxy file, since we have no way of retrieving the length of the type format string (and we do need a way of copying it, since it must be contiguous with ours). Instead the solution I propose is to use a script to parse the type format string (and the other parts that we need) into a generated file, to be done at build time. Since we need widl to do this, and since it can be done very easily in shell script, I have embedded it as a Makefile rule.
Makefile.in | 1 + dlls/rpcrt4/Makefile.in | 21 ++++++++++++++++++++- dlls/rpcrt4/ndr_typelib.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/Makefile.in b/Makefile.in index c1242afc01..25f535dc7f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -76,6 +76,7 @@ SUBDIRS = @SUBDIRS@ RUNTESTFLAGS = -q -P wine MAKEDEP = $(TOOLSDIR)/tools/makedep$(TOOLSEXT) WRC = $(TOOLSDIR)/tools/wrc/wrc$(TOOLSEXT) +WIDL = $(TOOLSDIR)/tools/widl/widl$(TOOLSEXT) PACKAGE_VERSION = @PACKAGE_VERSION@ SED_CMD = LC_ALL=C sed -e 's,@bindir@,$(bindir),g' -e 's,@dlldir@,$(dlldir),g' -e 's,@srcdir@,$(srcdir),g' -e 's,@PACKAGE_STRING@,@PACKAGE_STRING@,g' -e 's,@PACKAGE_VERSION@,@PACKAGE_VERSION@,g' LDRPATH_INSTALL = @LDRPATH_INSTALL@ diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in index ad67edf92e..aa80c2e7c7 100644 --- a/dlls/rpcrt4/Makefile.in +++ b/dlls/rpcrt4/Makefile.in @@ -2,7 +2,7 @@ EXTRADEFS = -D_RPCRT4_ -DMSWMSG MODULE = rpcrt4.dll IMPORTLIB = rpcrt4 IMPORTS = uuid advapi32 -DELAYIMPORTS = iphlpapi wininet secur32 user32 ws2_32 +DELAYIMPORTS = iphlpapi wininet secur32 user32 ws2_32 oleaut32
C_SRCS = \ cproxy.c \ @@ -28,3 +28,22 @@ C_SRCS = \ RC_SRCS = version.rc
IDL_SRCS = epm.idl
+EXTRA_OBJS = ndr_typelib_generated.o
+ndr_typelib_generated.c: $(WIDL)
- echo > ndr_typelib_generated.c '/* Automatically generated from Makefile.in, do not edit */' && \
- echo >> ndr_typelib_generated.c '#include "oaidl.h"' && \
- echo >> ndr_typelib_generated.c '#include "rpcproxy.h"' && \
- echo > ndr_typelib_generated.idl 'import "oaidl.idl"; [object] interface dummy {void dummy(BSTR a, IUnknown *b, IDispatch *c, VARIANT d, LPSAFEARRAY e); }' && \
- $(WIDL) $(WIDLFLAGS) -I $(top_srcdir)/include -p -o ndr_typelib_generated_p.c ndr_typelib_generated.idl && \
- echo >> ndr_typelib_generated.c 'const unsigned char oleaut_tfs[] = {' && \
- awk '/__MIDL_TypeFormatString =/,/};/' ndr_typelib_generated_p.c | head -n -2 | tail -n +5 >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c '};' && \
- sed -n -e 's/#define TYPE_FORMAT_STRING_SIZE ([0-9]+)/const size_t oleaut_tfs_size = \1;/p' ndr_typelib_generated_p.c >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c 'const unsigned short oleaut_offsets[] = {' && \
- sed -n -e 's/.*&__MIDL_TypeFormatString.Format[([0-9]+)].*/ \1,/p' ndr_typelib_generated_p.c | head -n 5 >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c '};' && \
- echo >> ndr_typelib_generated.c 'const USER_MARSHAL_ROUTINE_QUADRUPLE oleaut_user_marshal[] = ' && \
- awk '/UserMarshalRoutines[] =/,/};/' ndr_typelib_generated_p.c | tail -n +2 >> ndr_typelib_generated.c && \
- rm ndr_typelib_generated_p.c ndr_typelib_generated.idl
Did you consider adding a magic option to widl that would generate this table? IMHO, that would be much cleaner than this hack.
FWIW, "head -n -num" isn't supported by macOS's native head.
Huw.
On 11/5/18 4:12 AM, Huw Davies wrote:
On Sat, Nov 03, 2018 at 06:07:22PM -0500, Zebediah Figura wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
Automation types (BSTR, VARIANT, LPSAFEARRAY) are user-marshalled, which means that they require long format strings to represent the wire form of the data. Ideally this should be generated by widl at build time. However, we can't just create a dummy idl and retrieve the type format string from the generated proxy file, since we have no way of retrieving the length of the type format string (and we do need a way of copying it, since it must be contiguous with ours). Instead the solution I propose is to use a script to parse the type format string (and the other parts that we need) into a generated file, to be done at build time. Since we need widl to do this, and since it can be done very easily in shell script, I have embedded it as a Makefile rule.
Makefile.in | 1 + dlls/rpcrt4/Makefile.in | 21 ++++++++++++++++++++- dlls/rpcrt4/ndr_typelib.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/Makefile.in b/Makefile.in index c1242afc01..25f535dc7f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -76,6 +76,7 @@ SUBDIRS = @SUBDIRS@ RUNTESTFLAGS = -q -P wine MAKEDEP = $(TOOLSDIR)/tools/makedep$(TOOLSEXT) WRC = $(TOOLSDIR)/tools/wrc/wrc$(TOOLSEXT) +WIDL = $(TOOLSDIR)/tools/widl/widl$(TOOLSEXT) PACKAGE_VERSION = @PACKAGE_VERSION@ SED_CMD = LC_ALL=C sed -e 's,@bindir@,$(bindir),g' -e 's,@dlldir@,$(dlldir),g' -e 's,@srcdir@,$(srcdir),g' -e 's,@PACKAGE_STRING@,@PACKAGE_STRING@,g' -e 's,@PACKAGE_VERSION@,@PACKAGE_VERSION@,g' LDRPATH_INSTALL = @LDRPATH_INSTALL@ diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in index ad67edf92e..aa80c2e7c7 100644 --- a/dlls/rpcrt4/Makefile.in +++ b/dlls/rpcrt4/Makefile.in @@ -2,7 +2,7 @@ EXTRADEFS = -D_RPCRT4_ -DMSWMSG MODULE = rpcrt4.dll IMPORTLIB = rpcrt4 IMPORTS = uuid advapi32 -DELAYIMPORTS = iphlpapi wininet secur32 user32 ws2_32 +DELAYIMPORTS = iphlpapi wininet secur32 user32 ws2_32 oleaut32
C_SRCS = \ cproxy.c \ @@ -28,3 +28,22 @@ C_SRCS = \ RC_SRCS = version.rc
IDL_SRCS = epm.idl
+EXTRA_OBJS = ndr_typelib_generated.o
+ndr_typelib_generated.c: $(WIDL)
- echo > ndr_typelib_generated.c '/* Automatically generated from Makefile.in, do not edit */' && \
- echo >> ndr_typelib_generated.c '#include "oaidl.h"' && \
- echo >> ndr_typelib_generated.c '#include "rpcproxy.h"' && \
- echo > ndr_typelib_generated.idl 'import "oaidl.idl"; [object] interface dummy {void dummy(BSTR a, IUnknown *b, IDispatch *c, VARIANT d, LPSAFEARRAY e); }' && \
- $(WIDL) $(WIDLFLAGS) -I $(top_srcdir)/include -p -o ndr_typelib_generated_p.c ndr_typelib_generated.idl && \
- echo >> ndr_typelib_generated.c 'const unsigned char oleaut_tfs[] = {' && \
- awk '/__MIDL_TypeFormatString =/,/};/' ndr_typelib_generated_p.c | head -n -2 | tail -n +5 >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c '};' && \
- sed -n -e 's/#define TYPE_FORMAT_STRING_SIZE ([0-9]+)/const size_t oleaut_tfs_size = \1;/p' ndr_typelib_generated_p.c >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c 'const unsigned short oleaut_offsets[] = {' && \
- sed -n -e 's/.*&__MIDL_TypeFormatString.Format[([0-9]+)].*/ \1,/p' ndr_typelib_generated_p.c | head -n 5 >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c '};' && \
- echo >> ndr_typelib_generated.c 'const USER_MARSHAL_ROUTINE_QUADRUPLE oleaut_user_marshal[] = ' && \
- awk '/UserMarshalRoutines[] =/,/};/' ndr_typelib_generated_p.c | tail -n +2 >> ndr_typelib_generated.c && \
- rm ndr_typelib_generated_p.c ndr_typelib_generated.idl
Did you consider adding a magic option to widl that would generate this table? IMHO, that would be much cleaner than this hack.
FWIW, "head -n -num" isn't supported by macOS's native head.
Huw.
I believe I proposed it to Alexandre in an earlier conversation, and he seemed less than enthused, but I'll wait for his comment now that I've submitted the code.
Zebediah Figura z.figura12@gmail.com writes:
On 11/5/18 4:12 AM, Huw Davies wrote:
On Sat, Nov 03, 2018 at 06:07:22PM -0500, Zebediah Figura wrote:
+ndr_typelib_generated.c: $(WIDL)
- echo > ndr_typelib_generated.c '/* Automatically generated from Makefile.in, do not edit */' && \
- echo >> ndr_typelib_generated.c '#include "oaidl.h"' && \
- echo >> ndr_typelib_generated.c '#include "rpcproxy.h"' && \
- echo > ndr_typelib_generated.idl 'import "oaidl.idl"; [object] interface dummy {void dummy(BSTR a, IUnknown *b, IDispatch *c, VARIANT d, LPSAFEARRAY e); }' && \
- $(WIDL) $(WIDLFLAGS) -I $(top_srcdir)/include -p -o ndr_typelib_generated_p.c ndr_typelib_generated.idl && \
- echo >> ndr_typelib_generated.c 'const unsigned char oleaut_tfs[] = {' && \
- awk '/__MIDL_TypeFormatString =/,/};/' ndr_typelib_generated_p.c | head -n -2 | tail -n +5 >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c '};' && \
- sed -n -e 's/#define TYPE_FORMAT_STRING_SIZE ([0-9]+)/const size_t oleaut_tfs_size = \1;/p' ndr_typelib_generated_p.c >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c 'const unsigned short oleaut_offsets[] = {' && \
- sed -n -e 's/.*&__MIDL_TypeFormatString.Format[([0-9]+)].*/ \1,/p' ndr_typelib_generated_p.c | head -n 5 >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c '};' && \
- echo >> ndr_typelib_generated.c 'const USER_MARSHAL_ROUTINE_QUADRUPLE oleaut_user_marshal[] = ' && \
- awk '/UserMarshalRoutines[] =/,/};/' ndr_typelib_generated_p.c | tail -n +2 >> ndr_typelib_generated.c && \
- rm ndr_typelib_generated_p.c ndr_typelib_generated.idl
Did you consider adding a magic option to widl that would generate this table? IMHO, that would be much cleaner than this hack.
FWIW, "head -n -num" isn't supported by macOS's native head.
I believe I proposed it to Alexandre in an earlier conversation, and he seemed less than enthused, but I'll wait for his comment now that I've submitted the code.
A magic option is not great, but it would certainly be better than that ugly command sequence ;-)
On 11/05/2018 08:57 AM, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
On 11/5/18 4:12 AM, Huw Davies wrote:
On Sat, Nov 03, 2018 at 06:07:22PM -0500, Zebediah Figura wrote:
+ndr_typelib_generated.c: $(WIDL)
- echo > ndr_typelib_generated.c '/* Automatically generated from Makefile.in, do not edit */' && \
- echo >> ndr_typelib_generated.c '#include "oaidl.h"' && \
- echo >> ndr_typelib_generated.c '#include "rpcproxy.h"' && \
- echo > ndr_typelib_generated.idl 'import "oaidl.idl"; [object] interface dummy {void dummy(BSTR a, IUnknown *b, IDispatch *c, VARIANT d, LPSAFEARRAY e); }' && \
- $(WIDL) $(WIDLFLAGS) -I $(top_srcdir)/include -p -o ndr_typelib_generated_p.c ndr_typelib_generated.idl && \
- echo >> ndr_typelib_generated.c 'const unsigned char oleaut_tfs[] = {' && \
- awk '/__MIDL_TypeFormatString =/,/};/' ndr_typelib_generated_p.c | head -n -2 | tail -n +5 >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c '};' && \
- sed -n -e 's/#define TYPE_FORMAT_STRING_SIZE ([0-9]+)/const size_t oleaut_tfs_size = \1;/p' ndr_typelib_generated_p.c >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c 'const unsigned short oleaut_offsets[] = {' && \
- sed -n -e 's/.*&__MIDL_TypeFormatString.Format[([0-9]+)].*/ \1,/p' ndr_typelib_generated_p.c | head -n 5 >> ndr_typelib_generated.c && \
- echo >> ndr_typelib_generated.c '};' && \
- echo >> ndr_typelib_generated.c 'const USER_MARSHAL_ROUTINE_QUADRUPLE oleaut_user_marshal[] = ' && \
- awk '/UserMarshalRoutines[] =/,/};/' ndr_typelib_generated_p.c | tail -n +2 >> ndr_typelib_generated.c && \
- rm ndr_typelib_generated_p.c ndr_typelib_generated.idl
Did you consider adding a magic option to widl that would generate this table? IMHO, that would be much cleaner than this hack.
FWIW, "head -n -num" isn't supported by macOS's native head.
I believe I proposed it to Alexandre in an earlier conversation, and he seemed less than enthused, but I'll wait for his comment now that I've submitted the code.
A magic option is not great, but it would certainly be better than that ugly command sequence ;-)
Sure, understandable; I'll send a v2 of this patch using that approach.
I'd like to find a cleaner method than either, but I'm hard-pressed to think of one. If anyone has any other ideas, please feel free to speak.
In the meantime I'll wait for other comments, to avoid sending ten revisions of a fourteen-patch series ;-)
Zebediah Figura z.figura12@gmail.com writes:
On 11/05/2018 08:57 AM, Alexandre Julliard wrote:
A magic option is not great, but it would certainly be better than that ugly command sequence ;-)
Sure, understandable; I'll send a v2 of this patch using that approach.
I'd like to find a cleaner method than either, but I'm hard-pressed to think of one. If anyone has any other ideas, please feel free to speak.
I'd suggest something along these lines:
On 11/8/18 1:01 PM, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
On 11/05/2018 08:57 AM, Alexandre Julliard wrote:
A magic option is not great, but it would certainly be better than that ugly command sequence ;-)
Sure, understandable; I'll send a v2 of this patch using that approach.
I'd like to find a cleaner method than either, but I'm hard-pressed to think of one. If anyone has any other ideas, please feel free to speak.
I'd suggest something along these lines:
*snip*
This is a good idea, and I wish I'd thought of it ;-)
One possible concern I have is that widl isn't required to generate type format strings for individual parameters contiguously or in order. As things stand there's no reason for it not to, but that may not always be the case. For instance, MIDL is known to shorten the type format string by reusing entries for previously used types. I could see a widl implementation of this optimization being desirable, and possibly violating order constraints depending on how types are collapsed and written. Is this a salient concern?
Zebediah Figura z.figura12@gmail.com writes:
On 11/8/18 1:01 PM, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
On 11/05/2018 08:57 AM, Alexandre Julliard wrote:
A magic option is not great, but it would certainly be better than that ugly command sequence ;-)
Sure, understandable; I'll send a v2 of this patch using that approach.
I'd like to find a cleaner method than either, but I'm hard-pressed to think of one. If anyone has any other ideas, please feel free to speak.
I'd suggest something along these lines:
*snip*
This is a good idea, and I wish I'd thought of it ;-)
One possible concern I have is that widl isn't required to generate type format strings for individual parameters contiguously or in order. As things stand there's no reason for it not to, but that may not always be the case. For instance, MIDL is known to shorten the type format string by reusing entries for previously used types. I could see a widl implementation of this optimization being desirable, and possibly violating order constraints depending on how types are collapsed and written. Is this a salient concern?
If we add widl optimizations, we'll have to verify that the assumptions still hold, and possibly use different types. Hopefully the tests will catch any breakage.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index 687db1a5fa..5eb72af8c7 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -746,15 +746,40 @@ 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) { + ITypeInfo *real_typeinfo; TYPEATTR *typeattr; ITypeLib *typelib; TLIBATTR *libattr; + TYPEKIND typekind; + HREFTYPE reftype; SYSKIND syskind; HRESULT hr;
- hr = ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, NULL); + /* Dual interfaces report their size to be sizeof(IDispatchVtbl) and their + * implemented type to be IDispatch. We need to retrieve the underlying + * interface to get that information. */ + hr = ITypeInfo_GetTypeAttr(*typeinfo, &typeattr); + if (FAILED(hr)) + return hr; + typekind = typeattr->typekind; + ITypeInfo_ReleaseTypeAttr(*typeinfo, typeattr); + if (typekind == TKIND_DISPATCH) + { + hr = ITypeInfo_GetRefTypeOfImplType(*typeinfo, -1, &reftype); + if (FAILED(hr)) + return hr; + + hr = ITypeInfo_GetRefTypeInfo(*typeinfo, reftype, &real_typeinfo); + if (FAILED(hr)) + return hr; + + ITypeInfo_Release(*typeinfo); + *typeinfo = real_typeinfo; + } + + hr = ITypeInfo_GetContainingTypeLib(*typeinfo, &typelib, NULL); if (FAILED(hr)) return hr;
@@ -768,12 +793,12 @@ static HRESULT get_iface_info(ITypeInfo *typeinfo, WORD *funcs, WORD *parentfunc ITypeLib_ReleaseTLibAttr(typelib, libattr); ITypeLib_Release(typelib);
- hr = ITypeInfo_GetTypeAttr(typeinfo, &typeattr); + 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); + ITypeInfo_ReleaseTypeAttr(*typeinfo, typeattr);
return S_OK; } @@ -857,7 +882,7 @@ HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, IUnknown *outer, 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); if (FAILED(hr)) return hr;
@@ -970,7 +995,7 @@ HRESULT WINAPI CreateStubFromTypeInfo(ITypeInfo *typeinfo, REFIID iid, 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); if (FAILED(hr)) return hr;
Signed-off-by: Zebediah Figura z.figura12@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);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/rpcrt4/ndr_typelib.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index b06139eae0..0a985e76f6 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -648,6 +648,10 @@ static void write_proc_func_header(ITypeInfo *typeinfo, FUNCDESC *desc, WORD proc_idx, unsigned char *proc, size_t *proclen) { unsigned short stack_size = 2 * sizeof(void *); /* This + return */ +#ifdef __x86_64__ + unsigned short float_mask = 0; + unsigned char basetype; +#endif WORD param_idx;
WRITE_CHAR (proc, *proclen, FC_AUTO_HANDLE); @@ -659,8 +663,28 @@ static void write_proc_func_header(ITypeInfo *typeinfo, FUNCDESC *desc,
WRITE_SHORT(proc, *proclen, 0); /* constant_client_buffer_size */ WRITE_SHORT(proc, *proclen, 0); /* constant_server_buffer_size */ +#ifdef __x86_64__ + WRITE_CHAR (proc, *proclen, 0x47); /* HasExtensions | HasReturn | ClientMustSize | ServerMustSize */ +#else WRITE_CHAR (proc, *proclen, 0x07); /* HasReturn | ClientMustSize | ServerMustSize */ +#endif WRITE_CHAR (proc, *proclen, desc->cParams + 1); /* incl. return value */ +#ifdef __x86_64__ + WRITE_CHAR (proc, *proclen, 10); /* extension size */ + WRITE_CHAR (proc, *proclen, 0); /* INTERPRETER_OPT_FLAGS2 */ + WRITE_SHORT(proc, *proclen, 0); /* ClientCorrHint */ + WRITE_SHORT(proc, *proclen, 0); /* ServerCorrHint */ + WRITE_SHORT(proc, *proclen, 0); /* NotifyIndex */ + for (param_idx = 0; param_idx < desc->cParams && param_idx < 3; param_idx++) + { + basetype = get_base_type(desc->lprgelemdescParam[param_idx].tdesc.vt); + if (basetype == FC_FLOAT) + float_mask |= (1 << ((param_idx + 1) * 2)); + else if (basetype == FC_DOUBLE) + float_mask |= (2 << ((param_idx + 1) * 2)); + } + WRITE_SHORT(proc, *proclen, float_mask); +#endif }
static HRESULT write_iface_fs(ITypeInfo *typeinfo, WORD funcs, WORD parentfuncs,
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=14078 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=26768
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/oleaut32/Makefile.in | 1 - dlls/oleaut32/oleaut.c | 284 +++- dlls/oleaut32/tests/tmarshal.c | 24 +- dlls/oleaut32/tmarshal.c | 2351 -------------------------------- dlls/oleaut32/typelib.c | 32 - dlls/oleaut32/typelib.h | 6 - 6 files changed, 257 insertions(+), 2441 deletions(-) delete mode 100644 dlls/oleaut32/tmarshal.c
diff --git a/dlls/oleaut32/Makefile.in b/dlls/oleaut32/Makefile.in index 4c9d1d2ef1..a7dea7a37c 100644 --- a/dlls/oleaut32/Makefile.in +++ b/dlls/oleaut32/Makefile.in @@ -14,7 +14,6 @@ C_SRCS = \ olepropframe.c \ recinfo.c \ safearray.c \ - tmarshal.c \ typelib.c \ usrmarshal.c \ varformat.c \ diff --git a/dlls/oleaut32/oleaut.c b/dlls/oleaut32/oleaut.c index a12b45ec33..3161d5e1dd 100644 --- a/dlls/oleaut32/oleaut.c +++ b/dlls/oleaut32/oleaut.c @@ -21,6 +21,7 @@ #include "config.h"
#include <stdarg.h> +#include <stdio.h> #include <string.h> #include <limits.h>
@@ -766,6 +767,230 @@ extern BOOL WINAPI OLEAUTPS_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN; extern HRESULT WINAPI OLEAUTPS_DllRegisterServer(void) DECLSPEC_HIDDEN; extern HRESULT WINAPI OLEAUTPS_DllUnregisterServer(void) DECLSPEC_HIDDEN;
+extern HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo, + IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy, void **obj); +extern HRESULT WINAPI CreateStubFromTypeInfo(ITypeInfo *typeinfo, REFIID iid, + IUnknown *server, IRpcStubBuffer **stub); + +struct ifacepsredirect_data +{ + ULONG size; + DWORD mask; + GUID iid; + ULONG nummethods; + GUID tlbid; + GUID base; + ULONG name_len; + ULONG name_offset; +}; + +struct tlibredirect_data +{ + ULONG size; + DWORD res; + ULONG name_len; + ULONG name_offset; + LANGID langid; + WORD flags; + ULONG help_len; + ULONG help_offset; + WORD major_version; + WORD minor_version; +}; + +static BOOL actctx_get_typelib_module(REFIID iid, WCHAR *module, DWORD len) +{ + struct ifacepsredirect_data *iface; + struct tlibredirect_data *tlib; + ACTCTX_SECTION_KEYED_DATA data; + WCHAR *ptrW; + + data.cbSize = sizeof(data); + if (!FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION, + iid, &data)) + return FALSE; + + iface = (struct ifacepsredirect_data *)data.lpData; + if (!FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, + &iface->tlbid, &data)) + return FALSE; + + tlib = (struct tlibredirect_data *)data.lpData; + ptrW = (WCHAR *)((BYTE *)data.lpSectionBase + tlib->name_offset); + + if (tlib->name_len/sizeof(WCHAR) >= len) + { + ERR("need larger module buffer, %u\n", tlib->name_len); + return FALSE; + } + + memcpy(module, ptrW, tlib->name_len); + module[tlib->name_len/sizeof(WCHAR)] = 0; + return TRUE; +} + +static HRESULT reg_get_typelib_module(REFIID iid, WCHAR *module, DWORD len) +{ + REGSAM opposite = (sizeof(void*) == 8) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY; + char tlguid[200], typelibkey[300], interfacekey[300], ver[100], tlfn[260]; + DWORD tlguidlen, verlen, type; + LONG tlfnlen, err; + BOOL is_wow64; + HKEY ikey; + + sprintf( interfacekey, "Interface\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\Typelib", + iid->Data1, iid->Data2, iid->Data3, + iid->Data4[0], iid->Data4[1], iid->Data4[2], iid->Data4[3], + iid->Data4[4], iid->Data4[5], iid->Data4[6], iid->Data4[7] + ); + + err = RegOpenKeyExA(HKEY_CLASSES_ROOT,interfacekey,0,KEY_READ,&ikey); + if (err && (opposite == KEY_WOW64_32KEY || (IsWow64Process(GetCurrentProcess(), &is_wow64) + && is_wow64))) + err = RegOpenKeyExA(HKEY_CLASSES_ROOT,interfacekey,0,KEY_READ|opposite,&ikey); + + if (err) + { + ERR("No %s key found.\n", interfacekey); + return E_FAIL; + } + + tlguidlen = sizeof(tlguid); + if (RegQueryValueExA(ikey, NULL, NULL, &type, (BYTE *)tlguid, &tlguidlen)) + { + ERR("Getting typelib guid failed.\n"); + RegCloseKey(ikey); + return E_FAIL; + } + + verlen = sizeof(ver); + if (RegQueryValueExA(ikey, "Version", NULL, &type, (BYTE *)ver, &verlen)) + { + ERR("Could not get version value?\n"); + RegCloseKey(ikey); + return E_FAIL; + } + + RegCloseKey(ikey); + + sprintf(typelibkey, "Typelib\%s\%s\0\win%u", tlguid, ver, sizeof(void *) == 8 ? 64 : 32); + tlfnlen = sizeof(tlfn); + if (RegQueryValueA(HKEY_CLASSES_ROOT, typelibkey, tlfn, &tlfnlen)) + { +#ifdef _WIN64 + sprintf(typelibkey, "Typelib\%s\%s\0\win32", tlguid, ver); + tlfnlen = sizeof(tlfn); + if (RegQueryValueA(HKEY_CLASSES_ROOT, typelibkey, tlfn, &tlfnlen)) + { +#endif + ERR("Could not get typelib fn?\n"); + return E_FAIL; +#ifdef _WIN64 + } +#endif + } + MultiByteToWideChar(CP_ACP, 0, tlfn, -1, module, len); + return S_OK; +} + +static HRESULT get_typeinfo_for_iid(REFIID iid, ITypeInfo **typeinfo) +{ + WCHAR module[MAX_PATH]; + ITypeLib *typelib; + HRESULT hr; + + *typeinfo = NULL; + + module[0] = 0; + if (!actctx_get_typelib_module(iid, module, ARRAY_SIZE(module))) + { + hr = reg_get_typelib_module(iid, module, ARRAY_SIZE(module)); + if (FAILED(hr)) + return hr; + } + + hr = LoadTypeLib(module, &typelib); + if (hr != S_OK) { + ERR("Failed to load typelib for %s, but it should be there.\n", debugstr_guid(iid)); + return hr; + } + + hr = ITypeLib_GetTypeInfoOfGuid(typelib, iid, typeinfo); + ITypeLib_Release(typelib); + if (hr != S_OK) + ERR("typelib does not contain info for %s\n", debugstr_guid(iid)); + + return hr; +} + +static HRESULT WINAPI typelib_ps_QueryInterface(IPSFactoryBuffer *iface, REFIID iid, void **out) +{ + if (IsEqualIID(iid, &IID_IPSFactoryBuffer) || IsEqualIID(iid, &IID_IUnknown)) + { + *out = iface; + return S_OK; + } + + FIXME("No interface for %s.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI typelib_ps_AddRef(IPSFactoryBuffer *iface) +{ + return 2; +} + +static ULONG WINAPI typelib_ps_Release(IPSFactoryBuffer *iface) +{ + return 1; +} + +static HRESULT WINAPI typelib_ps_CreateProxy(IPSFactoryBuffer *iface, + IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy, void **out) +{ + ITypeInfo *typeinfo; + HRESULT hr; + + hr = get_typeinfo_for_iid(iid, &typeinfo); + if (FAILED(hr)) return hr; + + hr = CreateProxyFromTypeInfo(typeinfo, outer, iid, proxy, out); + if (FAILED(hr)) + ERR("Failed to create proxy, hr %#x.\n", hr); + + ITypeInfo_Release(typeinfo); + return hr; +} + +static HRESULT WINAPI typelib_ps_CreateStub(IPSFactoryBuffer *iface, REFIID iid, + IUnknown *server, IRpcStubBuffer **stub) +{ + ITypeInfo *typeinfo; + HRESULT hr; + + hr = get_typeinfo_for_iid(iid, &typeinfo); + if (FAILED(hr)) return hr; + + hr = CreateStubFromTypeInfo(typeinfo, iid, server, stub); + if (FAILED(hr)) + ERR("Failed to create stub, hr %#x.\n", hr); + + ITypeInfo_Release(typeinfo); + return hr; +} + +static const IPSFactoryBufferVtbl typelib_ps_vtbl = +{ + typelib_ps_QueryInterface, + typelib_ps_AddRef, + typelib_ps_Release, + typelib_ps_CreateProxy, + typelib_ps_CreateStub, +}; + +static IPSFactoryBuffer typelib_ps = { &typelib_ps_vtbl }; + extern void _get_STDFONT_CF(LPVOID *); extern void _get_STDPIC_CF(LPVOID *);
@@ -791,40 +1016,42 @@ static ULONG WINAPI PSDispatchFacBuf_Release(IPSFactoryBuffer *iface) return 1; }
-static HRESULT WINAPI PSDispatchFacBuf_CreateProxy(IPSFactoryBuffer *iface, IUnknown *pUnkOuter, REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv) +static HRESULT WINAPI PSDispatchFacBuf_CreateProxy(IPSFactoryBuffer *iface, + IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy, void **obj) { - IPSFactoryBuffer *pPSFB; + IPSFactoryBuffer *factory; HRESULT hr;
- if (IsEqualIID(riid, &IID_IDispatch)) - hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&pPSFB); - else - hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB); - - if (FAILED(hr)) return hr; - - hr = IPSFactoryBuffer_CreateProxy(pPSFB, pUnkOuter, riid, ppProxy, ppv); + if (IsEqualIID(iid, &IID_IDispatch)) + { + hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory); + if (FAILED(hr)) return hr;
- IPSFactoryBuffer_Release(pPSFB); - return hr; + hr = IPSFactoryBuffer_CreateProxy(factory, outer, iid, proxy, obj); + IPSFactoryBuffer_Release(factory); + return hr; + } + else + return IPSFactoryBuffer_CreateProxy(&typelib_ps, outer, iid, proxy, obj); }
-static HRESULT WINAPI PSDispatchFacBuf_CreateStub(IPSFactoryBuffer *iface, REFIID riid, IUnknown *pUnkOuter, IRpcStubBuffer **ppStub) +static HRESULT WINAPI PSDispatchFacBuf_CreateStub(IPSFactoryBuffer *iface, + REFIID iid, IUnknown *server, IRpcStubBuffer **stub) { - IPSFactoryBuffer *pPSFB; + IPSFactoryBuffer *factory; HRESULT hr;
- if (IsEqualIID(riid, &IID_IDispatch)) - hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&pPSFB); - else - hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB); - - if (FAILED(hr)) return hr; - - hr = IPSFactoryBuffer_CreateStub(pPSFB, riid, pUnkOuter, ppStub); + if (IsEqualIID(iid, &IID_IDispatch)) + { + hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory); + if (FAILED(hr)) return hr;
- IPSFactoryBuffer_Release(pPSFB); - return hr; + hr = IPSFactoryBuffer_CreateStub(factory, iid, server, stub); + IPSFactoryBuffer_Release(factory); + return hr; + } + else + return IPSFactoryBuffer_CreateStub(&typelib_ps, iid, server, stub); }
static const IPSFactoryBufferVtbl PSDispatchFacBuf_Vtbl = @@ -864,11 +1091,10 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) IPSFactoryBuffer_AddRef((IPSFactoryBuffer *)*ppv); return S_OK; } - if (IsEqualGUID(rclsid,&CLSID_PSOAInterface)) { - if (S_OK==TMARSHAL_DllGetClassObject(rclsid,iid,ppv)) - return S_OK; - /*FALLTHROUGH*/ - } + + if (IsEqualGUID(rclsid, &CLSID_PSOAInterface)) + return IPSFactoryBuffer_QueryInterface(&typelib_ps, iid, ppv); + if (IsEqualCLSID(rclsid, &CLSID_PSTypeComp) || IsEqualCLSID(rclsid, &CLSID_PSTypeInfo) || IsEqualCLSID(rclsid, &CLSID_PSTypeLib) || diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index c92e208795..8330b2e532 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -1010,7 +1010,6 @@ static HRESULT WINAPI Widget_int_ptr(IWidget *iface, int *in, int *out, int *in_
static HRESULT WINAPI Widget_int_ptr_ptr(IWidget *iface, int **in, int **out, int **in_out) { -todo_wine_if(testmode == 2) ok(!*out, "Got [out] %p.\n", *out); if (testmode == 0) { @@ -1078,7 +1077,6 @@ static HRESULT WINAPI Widget_iface_in(IWidget *iface, IUnknown *unk, IDispatch *
static HRESULT WINAPI Widget_iface_out(IWidget *iface, IUnknown **unk, IDispatch **disp, ISomethingFromDispatch **sfd) { -todo_wine ok(!*unk, "Got iface %p.\n", *unk); ok(!*disp, "Got iface %p.\n", *disp); ok(!*sfd, "Got iface %p.\n", *sfd); @@ -1138,7 +1136,6 @@ static HRESULT WINAPI Widget_bstr(IWidget *iface, BSTR in, BSTR *out, BSTR *in_p len = SysStringByteLen(in); ok(len == sizeof(test_bstr1), "Got wrong length %u.\n", len); ok(!memcmp(in, test_bstr1, len), "Got string %s.\n", wine_dbgstr_wn(in, len / sizeof(WCHAR))); -todo_wine_if(*out) ok(!*out, "Got unexpected output %p.\n", *out); len = SysStringLen(*in_ptr); ok(len == lstrlenW(test_bstr2), "Got wrong length %u.\n", len); @@ -1284,7 +1281,6 @@ static HRESULT WINAPI Widget_array(IWidget *iface, array_t in, array_t out, arra { static const array_t empty = {0}; ok(!memcmp(in, test_array1, sizeof(array_t)), "Arrays didn't match.\n"); -todo_wine ok(!memcmp(out, empty, sizeof(array_t)), "Arrays didn't match.\n"); ok(!memcmp(in_out, test_array3, sizeof(array_t)), "Arrays didn't match.\n");
@@ -1832,7 +1828,6 @@ static void test_marshal_pointer(IWidget *widget, IDispatch *disp) ok(out == 654, "Got [out] %d.\n", out); ok(in_out == 321, "Got [in, out] %d.\n", in_out);
-if (0) { out = in_out = -1; hr = IWidget_int_ptr(widget, NULL, &out, &in_out); ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr); @@ -1850,7 +1845,6 @@ if (0) { ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr); ok(in == -1, "[in] parameter should not have been cleared.\n"); ok(!out, "[out] parameter should have been cleared.\n"); -}
/* We can't test Invoke() with double pointers, as it is not possible to fit * more than one level of indirection into a VARIANTARG. */ @@ -1863,7 +1857,6 @@ if (0) { ok(!out_ptr, "Got [out] %p.\n", out_ptr); ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
-if (0) { testmode = 1; hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr); ok(hr == S_OK, "Got hr %#x\n", hr); @@ -1885,7 +1878,6 @@ if (0) { ok(in_out_ptr == &in_out, "[in, out] ptr should not have changed.\n"); ok(*out_ptr == 654, "Got [out] %d.\n", *out_ptr); ok(*in_out_ptr == 321, "Got [in, out] %d.\n", *in_out_ptr); -}
testmode = 3; in_ptr = out_ptr = NULL; @@ -1895,7 +1887,6 @@ if (0) { ok(hr == S_OK, "Got hr %#x.\n", hr); ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
-if (0) { out_ptr = &out; in_out_ptr = &in_out; hr = IWidget_int_ptr_ptr(widget, NULL, &out_ptr, &in_out_ptr); @@ -1917,7 +1908,6 @@ if (0) { ok(in_ptr == &in, "[in] parameter should not have been cleared.\n"); ok(!out_ptr, "[out] parameter should have been cleared.\n"); } -}
static void test_marshal_iface(IWidget *widget, IDispatch *disp) { @@ -1954,14 +1944,12 @@ static void test_marshal_iface(IWidget *widget, IDispatch *disp) release_iface(proxy_disp); release_iface(proxy_sfd);
-if (0) { testmode = 1; hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd); ok(hr == S_OK, "Got hr %#x.\n", hr); ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk); ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp); ok(!proxy_sfd, "Got unexpected proxy %p.\n", proxy_sfd); -}
testmode = 0; sfd_in = sfd1 = create_disp_obj(); @@ -1974,7 +1962,6 @@ if (0) { ok(sfd_in_out == sfd3, "[in, out] parameter should not have changed.\n"); release_iface(sfd1); release_iface(sfd2); -todo_wine release_iface(sfd3);
testmode = 1; @@ -1991,7 +1978,6 @@ todo_wine release_iface(sfd_out); release_iface(sfd_in_out); release_iface(sfd1); -todo_wine release_iface(sfd3);
testmode = 2; @@ -2010,7 +1996,6 @@ todo_wine hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out); ok(hr == S_OK, "Got hr %#x.\n", hr); ok(!sfd_in_out, "Got [in, out] %p.\n", sfd_in_out); -todo_wine release_iface(sfd3);
/* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our @@ -2331,17 +2316,14 @@ static void test_marshal_array(IWidget *widget, IDispatch *disp) MYSTRUCT struct_in[2]; HRESULT hr;
-if (0) { memcpy(in, test_array1, sizeof(array_t)); memcpy(out, test_array2, sizeof(array_t)); memcpy(in_out, test_array3, sizeof(array_t)); hr = IWidget_array(widget, in, out, in_out); ok(hr == S_OK, "Got hr %#x.\n", hr); -todo_wine ok(!memcmp(&in, &test_array1, sizeof(array_t)), "Arrays didn't match.\n"); ok(!memcmp(&out, &test_array5, sizeof(array_t)), "Arrays didn't match.\n"); ok(!memcmp(&in_out, &test_array6, sizeof(array_t)), "Arrays didn't match.\n"); -}
V_VT(&var_in[0]) = VT_I4; V_I4(&var_in[0]) = 1; V_VT(&var_in[1]) = VT_I4; V_I4(&var_in[1]) = 2; @@ -2355,7 +2337,6 @@ todo_wine ok(V_I4(&var_in[0]) == 1, "Got wrong value %d.\n", V_I4(&var_in[0])); ok(V_VT(&var_in[1]) == VT_I4, "Got wrong type %u.\n", V_VT(&var_in[1])); ok(V_I4(&var_in[1]) == 2, "Got wrong value %d.\n", V_I4(&var_in[1])); -todo_wine { ok(V_VT(&var_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_out[0])); ok(V_I1(&var_out[0]) == 9, "Got wrong value %u.\n", V_VT(&var_out[0])); ok(V_VT(&var_out[1]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_out[1])); @@ -2364,7 +2345,6 @@ todo_wine { ok(V_I1(&var_in_out[0]) == 11, "Got wrong value %u.\n", V_VT(&var_in_out[0])); ok(V_VT(&var_in_out[1]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_in_out[1])); ok(V_I1(&var_in_out[1]) == 12, "Got wrong value %u.\n", V_VT(&var_in_out[1])); -}
memcpy(&struct_in[0], &test_mystruct1, sizeof(MYSTRUCT)); memcpy(&struct_in[1], &test_mystruct2, sizeof(MYSTRUCT)); @@ -2404,7 +2384,7 @@ static void test_typelibmarshal(void)
IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW); -#ifndef __i386__ +#if !defined(__i386__) && !defined(__x86_64__) todo_wine #endif ok_ole_success(hr, CoUnmarshalInterface); @@ -3080,7 +3060,7 @@ static void test_external_connection(void)
IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface); -#ifndef __i386__ +#if !defined(__i386__) && !defined(__x86_64__) todo_wine #endif ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres); diff --git a/dlls/oleaut32/tmarshal.c b/dlls/oleaut32/tmarshal.c deleted file mode 100644 index 1e1688e690..0000000000 --- a/dlls/oleaut32/tmarshal.c +++ /dev/null @@ -1,2351 +0,0 @@ -/* - * TYPELIB Marshaler - * - * Copyright 2002,2005 Marcus Meissner - * - * The olerelay debug channel allows you to see calls marshalled by - * the typelib marshaller. It is not a generic COM relaying system. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "config.h" -#include "wine/port.h" - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <stdio.h> -#include <ctype.h> - -#define COBJMACROS -#define NONAMELESSUNION - -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#include "winreg.h" -#include "winuser.h" - -#include "ole2.h" -#include "propidl.h" /* for LPSAFEARRAY_User* functions */ -#include "typelib.h" -#include "variant.h" -#include "wine/debug.h" -#include "wine/exception.h" - -static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0}; - -WINE_DEFAULT_DEBUG_CHANNEL(ole); -WINE_DECLARE_DEBUG_CHANNEL(olerelay); - -static HRESULT TMarshalDispatchChannel_Create( - IRpcChannelBuffer *pDelegateChannel, REFIID tmarshal_riid, - IRpcChannelBuffer **ppChannel); - -typedef struct _marshal_state { - LPBYTE base; - int size; - int curoff; -} marshal_state; - -/* used in the olerelay code to avoid having the L"" stuff added by debugstr_w */ -static char *relaystr(WCHAR *in) { - char *tmp = (char *)debugstr_w(in); - tmp += 2; - tmp[strlen(tmp)-1] = '\0'; - return tmp; -} - -static HRESULT -xbuf_resize(marshal_state *buf, DWORD newsize) -{ - if(buf->size >= newsize) - return S_FALSE; - - if(buf->base) - { - newsize = max(newsize, buf->size * 2); - buf->base = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buf->base, newsize); - if(!buf->base) - return E_OUTOFMEMORY; - } - else - { - newsize = max(newsize, 256); - buf->base = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newsize); - if(!buf->base) - return E_OUTOFMEMORY; - } - buf->size = newsize; - return S_OK; -} - -static HRESULT -xbuf_add(marshal_state *buf, const BYTE *stuff, DWORD size) -{ - HRESULT hr; - - if(buf->size - buf->curoff < size) - { - hr = xbuf_resize(buf, buf->size + size); - if(FAILED(hr)) return hr; - } - memcpy(buf->base+buf->curoff,stuff,size); - buf->curoff += size; - return S_OK; -} - -static HRESULT -xbuf_get(marshal_state *buf, LPBYTE stuff, DWORD size) { - if (buf->size < buf->curoff+size) return E_FAIL; - memcpy(stuff,buf->base+buf->curoff,size); - buf->curoff += size; - return S_OK; -} - -static HRESULT -xbuf_skip(marshal_state *buf, DWORD size) { - if (buf->size < buf->curoff+size) return E_FAIL; - buf->curoff += size; - return S_OK; -} - -static HRESULT -_unmarshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN *pUnk) { - IStream *pStm; - ULARGE_INTEGER newpos; - LARGE_INTEGER seekto; - ULONG res; - HRESULT hres; - DWORD xsize; - - TRACE("...%s...\n",debugstr_guid(riid)); - - *pUnk = NULL; - hres = xbuf_get(buf,(LPBYTE)&xsize,sizeof(xsize)); - if (hres) { - ERR("xbuf_get failed\n"); - return hres; - } - - if (xsize == 0) return S_OK; - - hres = CreateStreamOnHGlobal(0,TRUE,&pStm); - if (hres) { - ERR("Stream create failed %x\n",hres); - return hres; - } - - hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res); - if (hres) { - ERR("stream write %x\n",hres); - IStream_Release(pStm); - return hres; - } - - memset(&seekto,0,sizeof(seekto)); - hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); - if (hres) { - ERR("Failed Seek %x\n",hres); - IStream_Release(pStm); - return hres; - } - - hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk); - if (hres) { - ERR("Unmarshalling interface %s failed with %x\n",debugstr_guid(riid),hres); - IStream_Release(pStm); - return hres; - } - - IStream_Release(pStm); - return xbuf_skip(buf,xsize); -} - -static HRESULT -_marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) { - LPBYTE tempbuf = NULL; - IStream *pStm = NULL; - STATSTG ststg; - ULARGE_INTEGER newpos; - LARGE_INTEGER seekto; - ULONG res; - DWORD xsize; - HRESULT hres; - - if (!pUnk) { - /* this is valid, if for instance we serialize - * a VT_DISPATCH with NULL ptr which apparently - * can happen. S_OK to make sure we continue - * serializing. - */ - WARN("pUnk is NULL\n"); - xsize = 0; - return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); - } - - TRACE("...%s...\n",debugstr_guid(riid)); - - hres = CreateStreamOnHGlobal(0,TRUE,&pStm); - if (hres) { - ERR("Stream create failed %x\n",hres); - goto fail; - } - - hres = CoMarshalInterface(pStm,riid,pUnk,0,NULL,0); - if (hres) { - ERR("Marshalling interface %s failed with %x\n", debugstr_guid(riid), hres); - goto fail; - } - - hres = IStream_Stat(pStm,&ststg,STATFLAG_NONAME); - if (hres) { - ERR("Stream stat failed\n"); - goto fail; - } - - tempbuf = HeapAlloc(GetProcessHeap(), 0, ststg.cbSize.u.LowPart); - memset(&seekto,0,sizeof(seekto)); - hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); - if (hres) { - ERR("Failed Seek %x\n",hres); - goto fail; - } - - hres = IStream_Read(pStm,tempbuf,ststg.cbSize.u.LowPart,&res); - if (hres) { - ERR("Failed Read %x\n",hres); - goto fail; - } - - xsize = ststg.cbSize.u.LowPart; - xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); - hres = xbuf_add(buf,tempbuf,ststg.cbSize.u.LowPart); - - HeapFree(GetProcessHeap(),0,tempbuf); - IStream_Release(pStm); - - return hres; - -fail: - xsize = 0; - xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); - if (pStm) IStream_Release(pStm); - HeapFree(GetProcessHeap(), 0, tempbuf); - return hres; -} - -/********************* OLE Proxy/Stub Factory ********************************/ -static HRESULT WINAPI -PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) { - if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) { - *ppv = iface; - /* No ref counting, static class */ - return S_OK; - } - FIXME("(%s) unknown IID?\n",debugstr_guid(iid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; } -static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; } - -struct ifacepsredirect_data -{ - ULONG size; - DWORD mask; - GUID iid; - ULONG nummethods; - GUID tlbid; - GUID base; - ULONG name_len; - ULONG name_offset; -}; - -struct tlibredirect_data -{ - ULONG size; - DWORD res; - ULONG name_len; - ULONG name_offset; - LANGID langid; - WORD flags; - ULONG help_len; - ULONG help_offset; - WORD major_version; - WORD minor_version; -}; - -static BOOL actctx_get_typelib_module(REFIID riid, WCHAR *module, DWORD len) -{ - struct ifacepsredirect_data *iface; - struct tlibredirect_data *tlib; - ACTCTX_SECTION_KEYED_DATA data; - WCHAR *ptrW; - - data.cbSize = sizeof(data); - if (!FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION, - riid, &data)) - return FALSE; - - iface = (struct ifacepsredirect_data*)data.lpData; - if (!FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, - &iface->tlbid, &data)) - return FALSE; - - tlib = (struct tlibredirect_data*)data.lpData; - ptrW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset); - - if (tlib->name_len/sizeof(WCHAR) >= len) { - ERR("need larger module buffer, %u\n", tlib->name_len); - return FALSE; - } - - memcpy(module, ptrW, tlib->name_len); - module[tlib->name_len/sizeof(WCHAR)] = 0; - return TRUE; -} - -static HRESULT reg_get_typelib_module(REFIID riid, WCHAR *module, DWORD len) -{ - HKEY ikey; - REGSAM opposite = (sizeof(void*) == 8) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY; - BOOL is_wow64; - char tlguid[200],typelibkey[300],interfacekey[300],ver[100]; - char tlfn[260]; - DWORD tlguidlen, verlen, type; - LONG tlfnlen, err; - - sprintf( interfacekey, "Interface\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\Typelib", - riid->Data1, riid->Data2, riid->Data3, - riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], - riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] - ); - - err = RegOpenKeyExA(HKEY_CLASSES_ROOT,interfacekey,0,KEY_READ,&ikey); - if (err && (opposite == KEY_WOW64_32KEY || (IsWow64Process(GetCurrentProcess(), &is_wow64) - && is_wow64))) { - err = RegOpenKeyExA(HKEY_CLASSES_ROOT,interfacekey,0,KEY_READ|opposite,&ikey); - } - if (err) { - ERR("No %s key found.\n",interfacekey); - return E_FAIL; - } - tlguidlen = sizeof(tlguid); - if (RegQueryValueExA(ikey,NULL,NULL,&type,(LPBYTE)tlguid,&tlguidlen)) { - ERR("Getting typelib guid failed.\n"); - RegCloseKey(ikey); - return E_FAIL; - } - verlen = sizeof(ver); - if (RegQueryValueExA(ikey,"Version",NULL,&type,(LPBYTE)ver,&verlen)) { - ERR("Could not get version value?\n"); - RegCloseKey(ikey); - return E_FAIL; - } - RegCloseKey(ikey); - sprintf(typelibkey,"Typelib\%s\%s\0\win%u",tlguid,ver,(sizeof(void*) == 8) ? 64 : 32); - tlfnlen = sizeof(tlfn); - if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) { -#ifdef _WIN64 - sprintf(typelibkey,"Typelib\%s\%s\0\win32",tlguid,ver); - tlfnlen = sizeof(tlfn); - if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) { -#endif - ERR("Could not get typelib fn?\n"); - return E_FAIL; -#ifdef _WIN64 - } -#endif - } - MultiByteToWideChar(CP_ACP, 0, tlfn, -1, module, len); - return S_OK; -} - -static HRESULT -_get_typeinfo_for_iid(REFIID riid, ITypeInfo **typeinfo) -{ - OLECHAR moduleW[260]; - ITypeLib *typelib; - HRESULT hres; - - *typeinfo = NULL; - - moduleW[0] = 0; - if (!actctx_get_typelib_module(riid, moduleW, ARRAY_SIZE(moduleW))) { - hres = reg_get_typelib_module(riid, moduleW, ARRAY_SIZE(moduleW)); - if (FAILED(hres)) - return hres; - } - - hres = LoadTypeLib(moduleW, &typelib); - if (hres != S_OK) { - ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid)); - return hres; - } - - hres = ITypeLib_GetTypeInfoOfGuid(typelib, riid, typeinfo); - ITypeLib_Release(typelib); - if (hres != S_OK) - ERR("typelib does not contain info for %s\n", debugstr_guid(riid)); - - return hres; -} - -/* - * Determine the number of functions including all inherited functions - * and well as the size of the vtbl. - * Note for non-dual dispinterfaces we simply return the size of IDispatch. - */ -static HRESULT num_of_funcs(ITypeInfo *tinfo, unsigned int *num, - unsigned int *vtbl_size) -{ - HRESULT hr; - TYPEATTR *attr; - ITypeInfo *tinfo2; - UINT inherited_funcs = 0, i; - - *num = 0; - if(vtbl_size) *vtbl_size = 0; - - hr = ITypeInfo_GetTypeAttr(tinfo, &attr); - if (hr) - { - ERR("GetTypeAttr failed with %x\n", hr); - return hr; - } - - if(attr->typekind == TKIND_DISPATCH) - { - if(attr->wTypeFlags & TYPEFLAG_FDUAL) - { - HREFTYPE href; - - ITypeInfo_ReleaseTypeAttr(tinfo, attr); - hr = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href); - if(FAILED(hr)) - { - ERR("Unable to get interface href from dual dispinterface\n"); - return hr; - } - hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); - if(FAILED(hr)) - { - ERR("Unable to get interface from dual dispinterface\n"); - return hr; - } - hr = num_of_funcs(tinfo2, num, vtbl_size); - ITypeInfo_Release(tinfo2); - return hr; - } - else /* non-dual dispinterface */ - { - /* These will be the size of IDispatchVtbl */ - *num = attr->cbSizeVft / sizeof(void *); - if(vtbl_size) *vtbl_size = attr->cbSizeVft; - ITypeInfo_ReleaseTypeAttr(tinfo, attr); - return hr; - } - } - - for (i = 0; i < attr->cImplTypes; i++) - { - HREFTYPE href; - ITypeInfo *pSubTypeInfo; - UINT sub_funcs; - - hr = ITypeInfo_GetRefTypeOfImplType(tinfo, i, &href); - if (FAILED(hr)) goto end; - hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &pSubTypeInfo); - if (FAILED(hr)) goto end; - - hr = num_of_funcs(pSubTypeInfo, &sub_funcs, NULL); - ITypeInfo_Release(pSubTypeInfo); - - if(FAILED(hr)) goto end; - inherited_funcs += sub_funcs; - } - - *num = inherited_funcs + attr->cFuncs; - if(vtbl_size) *vtbl_size = attr->cbSizeVft; - - end: - ITypeInfo_ReleaseTypeAttr(tinfo, attr); - return hr; -} - -#ifdef __i386__ - -#include "pshpack1.h" - -typedef struct _TMAsmProxy { - DWORD lealeax; - BYTE pushleax; - BYTE pushlval; - DWORD nr; - BYTE lcall; - DWORD xcall; - BYTE lret; - WORD bytestopop; - WORD nop; -} TMAsmProxy; - -#include "poppack.h" - -#else /* __i386__ */ -# warning You need to implement stubless proxies for your architecture -typedef struct _TMAsmProxy { -} TMAsmProxy; -#endif - -typedef struct _TMProxyImpl { - LPVOID *lpvtbl; - IRpcProxyBuffer IRpcProxyBuffer_iface; - LONG ref; - - TMAsmProxy *asmstubs; - ITypeInfo* tinfo; - IRpcChannelBuffer* chanbuf; - IID iid; - CRITICAL_SECTION crit; - IUnknown *outerunknown; - IDispatch *dispatch; - IRpcProxyBuffer *dispatch_proxy; -} TMProxyImpl; - -static inline TMProxyImpl *impl_from_IRpcProxyBuffer( IRpcProxyBuffer *iface ) -{ - return CONTAINING_RECORD(iface, TMProxyImpl, IRpcProxyBuffer_iface); -} - -static HRESULT WINAPI -TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv) -{ - TRACE("()\n"); - if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) { - *ppv = iface; - IRpcProxyBuffer_AddRef(iface); - return S_OK; - } - FIXME("no interface for %s\n",debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI -TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface) -{ - TMProxyImpl *This = impl_from_IRpcProxyBuffer( iface ); - ULONG refCount = InterlockedIncrement(&This->ref); - - TRACE("(%p)->(ref before=%u)\n",This, refCount - 1); - - return refCount; -} - -static ULONG WINAPI -TMProxyImpl_Release(LPRPCPROXYBUFFER iface) -{ - TMProxyImpl *This = impl_from_IRpcProxyBuffer( iface ); - ULONG refCount = InterlockedDecrement(&This->ref); - - TRACE("(%p)->(ref before=%u)\n",This, refCount + 1); - - if (!refCount) - { - if (This->dispatch_proxy) IRpcProxyBuffer_Release(This->dispatch_proxy); - This->crit.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->crit); - if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf); - VirtualFree(This->asmstubs, 0, MEM_RELEASE); - HeapFree(GetProcessHeap(), 0, This->lpvtbl); - ITypeInfo_Release(This->tinfo); - CoTaskMemFree(This); - } - return refCount; -} - -static HRESULT WINAPI -TMProxyImpl_Connect( - LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer) -{ - TMProxyImpl *This = impl_from_IRpcProxyBuffer( iface ); - - TRACE("(%p)\n", pRpcChannelBuffer); - - EnterCriticalSection(&This->crit); - - IRpcChannelBuffer_AddRef(pRpcChannelBuffer); - This->chanbuf = pRpcChannelBuffer; - - LeaveCriticalSection(&This->crit); - - if (This->dispatch_proxy) - { - IRpcChannelBuffer *pDelegateChannel; - HRESULT hr = TMarshalDispatchChannel_Create(pRpcChannelBuffer, &This->iid, &pDelegateChannel); - if (FAILED(hr)) - return hr; - hr = IRpcProxyBuffer_Connect(This->dispatch_proxy, pDelegateChannel); - IRpcChannelBuffer_Release(pDelegateChannel); - return hr; - } - - return S_OK; -} - -static void WINAPI -TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface) -{ - TMProxyImpl *This = impl_from_IRpcProxyBuffer( iface ); - - TRACE("()\n"); - - EnterCriticalSection(&This->crit); - - IRpcChannelBuffer_Release(This->chanbuf); - This->chanbuf = NULL; - - LeaveCriticalSection(&This->crit); - - if (This->dispatch_proxy) - IRpcProxyBuffer_Disconnect(This->dispatch_proxy); -} - - -static const IRpcProxyBufferVtbl tmproxyvtable = { - TMProxyImpl_QueryInterface, - TMProxyImpl_AddRef, - TMProxyImpl_Release, - TMProxyImpl_Connect, - TMProxyImpl_Disconnect -}; - -/* how much space do we use on stack in DWORD steps. */ -static int -_argsize(TYPEDESC *tdesc, ITypeInfo *tinfo) { - switch (tdesc->vt) { - case VT_I8: - case VT_UI8: - return 8/sizeof(DWORD); - case VT_R8: - return sizeof(double)/sizeof(DWORD); - case VT_CY: - return sizeof(CY)/sizeof(DWORD); - case VT_DATE: - return sizeof(DATE)/sizeof(DWORD); - case VT_DECIMAL: - return (sizeof(DECIMAL)+3)/sizeof(DWORD); - case VT_VARIANT: - return (sizeof(VARIANT)+3)/sizeof(DWORD); - case VT_USERDEFINED: - { - ITypeInfo *tinfo2; - TYPEATTR *tattr; - HRESULT hres; - DWORD ret; - - hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); - if (FAILED(hres)) - return 0; /* should fail critically in serialize_param */ - ITypeInfo_GetTypeAttr(tinfo2,&tattr); - ret = (tattr->cbSizeInstance+3)/sizeof(DWORD); - ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); - ITypeInfo_Release(tinfo2); - return ret; - } - default: - return 1; - } -} - -/* how much space do we use on the heap (in bytes) */ -static int -_xsize(const TYPEDESC *td, ITypeInfo *tinfo) { - switch (td->vt) { - case VT_DATE: - return sizeof(DATE); - case VT_CY: - return sizeof(CY); - case VT_VARIANT: - return sizeof(VARIANT); - case VT_CARRAY: { - int i, arrsize = 1; - const ARRAYDESC *adesc = td->u.lpadesc; - - for (i=0;i<adesc->cDims;i++) - arrsize *= adesc->rgbounds[i].cElements; - return arrsize*_xsize(&adesc->tdescElem, tinfo); - } - case VT_UI8: - case VT_I8: - case VT_R8: - return 8; - case VT_UI2: - case VT_I2: - case VT_BOOL: - return 2; - case VT_UI1: - case VT_I1: - return 1; - case VT_USERDEFINED: - { - ITypeInfo *tinfo2; - TYPEATTR *tattr; - HRESULT hres; - DWORD ret; - - hres = ITypeInfo_GetRefTypeInfo(tinfo,td->u.hreftype,&tinfo2); - if (FAILED(hres)) - return 0; - ITypeInfo_GetTypeAttr(tinfo2,&tattr); - ret = tattr->cbSizeInstance; - ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); - ITypeInfo_Release(tinfo2); - return ret; - } - default: - return 4; - } -} - -/* Whether we pass this type by reference or by value */ -static BOOL -_passbyref(const TYPEDESC *td, ITypeInfo *tinfo) { - return (td->vt == VT_USERDEFINED || - td->vt == VT_VARIANT || - td->vt == VT_PTR); -} - -static HRESULT -serialize_param( - ITypeInfo *tinfo, - BOOL writeit, - BOOL debugout, - BOOL dealloc, - TYPEDESC *tdesc, - DWORD *arg, - marshal_state *buf) -{ - HRESULT hres = S_OK; - VARTYPE vartype; - - TRACE("(tdesc.vt %s)\n",debugstr_vt(tdesc->vt)); - - vartype = tdesc->vt; - if ((vartype & 0xf000) == VT_ARRAY) - vartype = VT_SAFEARRAY; - - switch (vartype) { - case VT_DATE: - case VT_I8: - case VT_UI8: - case VT_R8: - case VT_CY: - hres = S_OK; - if (debugout) TRACE_(olerelay)("%x%x\n",arg[0],arg[1]); - if (writeit) - hres = xbuf_add(buf,(LPBYTE)arg,8); - return hres; - case VT_ERROR: - case VT_INT: - case VT_UINT: - case VT_I4: - case VT_R4: - case VT_UI4: - hres = S_OK; - if (debugout) TRACE_(olerelay)("%x\n",*arg); - if (writeit) - hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); - return hres; - case VT_I2: - case VT_UI2: - case VT_BOOL: - hres = S_OK; - if (debugout) TRACE_(olerelay)("%04x\n",*arg & 0xffff); - if (writeit) - hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); - return hres; - case VT_I1: - case VT_UI1: - hres = S_OK; - if (debugout) TRACE_(olerelay)("%02x\n",*arg & 0xff); - if (writeit) - hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); - return hres; - case VT_VARIANT: { - if (debugout) TRACE_(olerelay)("%s", debugstr_variant((VARIANT *)arg)); - if (writeit) - { - ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); - ULONG size = VARIANT_UserSize(&flags, buf->curoff, (VARIANT *)arg); - xbuf_resize(buf, size); - VARIANT_UserMarshal(&flags, buf->base + buf->curoff, (VARIANT *)arg); - buf->curoff = size; - } - if (dealloc) - { - ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); - VARIANT_UserFree(&flags, (VARIANT *)arg); - } - return S_OK; - } - case VT_BSTR: { - if (writeit && debugout) { - if (*arg) - TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg)); - else - TRACE_(olerelay)("<bstr NULL>"); - } - if (writeit) - { - ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); - ULONG size = BSTR_UserSize(&flags, buf->curoff, (BSTR *)arg); - xbuf_resize(buf, size); - BSTR_UserMarshal(&flags, buf->base + buf->curoff, (BSTR *)arg); - buf->curoff = size; - } - if (dealloc) - { - ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); - BSTR_UserFree(&flags, (BSTR *)arg); - } - return S_OK; - } - case VT_PTR: { - DWORD cookie; - BOOL derefhere = TRUE; - - if (tdesc->u.lptdesc->vt == VT_USERDEFINED) { - ITypeInfo *tinfo2; - TYPEATTR *tattr; - - hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2); - if (hres) { - ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype); - return hres; - } - ITypeInfo_GetTypeAttr(tinfo2,&tattr); - switch (tattr->typekind) { - case TKIND_ALIAS: - if (tattr->tdescAlias.vt == VT_USERDEFINED) - { - DWORD href = tattr->tdescAlias.u.hreftype; - ITypeInfo_ReleaseTypeAttr(tinfo, tattr); - ITypeInfo_Release(tinfo2); - hres = ITypeInfo_GetRefTypeInfo(tinfo,href,&tinfo2); - if (hres) { - ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype); - return hres; - } - ITypeInfo_GetTypeAttr(tinfo2,&tattr); - derefhere = (tattr->typekind != TKIND_DISPATCH && tattr->typekind != TKIND_INTERFACE); - } - break; - case TKIND_ENUM: /* confirmed */ - case TKIND_RECORD: /* FIXME: mostly untested */ - break; - case TKIND_DISPATCH: /* will be done in VT_USERDEFINED case */ - case TKIND_INTERFACE: /* will be done in VT_USERDEFINED case */ - derefhere=FALSE; - break; - default: - FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind); - derefhere=FALSE; - break; - } - ITypeInfo_ReleaseTypeAttr(tinfo, tattr); - ITypeInfo_Release(tinfo2); - } - - if (debugout) TRACE_(olerelay)("*"); - /* Write always, so the other side knows when it gets a NULL pointer. - */ - cookie = *arg ? 0x42424242 : 0; - hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie)); - if (hres) - return hres; - if (!*arg) { - if (debugout) TRACE_(olerelay)("NULL"); - return S_OK; - } - hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf); - if (derefhere && dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)*arg); - return hres; - } - case VT_UNKNOWN: - if (debugout) TRACE_(olerelay)("unk(0x%x)",*arg); - if (writeit) - hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg); - if (dealloc && *(IUnknown **)arg) - IUnknown_Release((LPUNKNOWN)*arg); - return hres; - case VT_DISPATCH: - if (debugout) TRACE_(olerelay)("idisp(0x%x)",*arg); - if (writeit) - hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg); - if (dealloc && *(IUnknown **)arg) - IUnknown_Release((LPUNKNOWN)*arg); - return hres; - case VT_VOID: - if (debugout) TRACE_(olerelay)("<void>"); - return S_OK; - case VT_USERDEFINED: { - ITypeInfo *tinfo2; - TYPEATTR *tattr; - - hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); - if (hres) { - ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype); - return hres; - } - ITypeInfo_GetTypeAttr(tinfo2,&tattr); - switch (tattr->typekind) { - case TKIND_DISPATCH: - case TKIND_INTERFACE: - if (writeit) - hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg); - if (dealloc) - IUnknown_Release((LPUNKNOWN)arg); - break; - case TKIND_RECORD: { - int i; - if (debugout) TRACE_(olerelay)("{"); - for (i=0;i<tattr->cVars;i++) { - VARDESC *vdesc; - ELEMDESC *elem2; - TYPEDESC *tdesc2; - - hres = ITypeInfo_GetVarDesc(tinfo2, i, &vdesc); - if (hres) { - ERR("Could not get vardesc of %d\n",i); - return hres; - } - elem2 = &vdesc->elemdescVar; - tdesc2 = &elem2->tdesc; - hres = serialize_param( - tinfo2, - writeit, - debugout, - dealloc, - tdesc2, - (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst), - buf - ); - ITypeInfo_ReleaseVarDesc(tinfo2, vdesc); - if (hres!=S_OK) - return hres; - if (debugout && (i<(tattr->cVars-1))) - TRACE_(olerelay)(","); - } - if (debugout) TRACE_(olerelay)("}"); - break; - } - case TKIND_ALIAS: - hres = serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf); - break; - case TKIND_ENUM: - hres = S_OK; - if (debugout) TRACE_(olerelay)("%x",*arg); - if (writeit) - hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); - break; - default: - FIXME("Unhandled typekind %d\n",tattr->typekind); - hres = E_FAIL; - break; - } - ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); - ITypeInfo_Release(tinfo2); - return hres; - } - case VT_CARRAY: { - ARRAYDESC *adesc = tdesc->u.lpadesc; - int i, arrsize = 1; - - if (debugout) TRACE_(olerelay)("carr"); - for (i=0;i<adesc->cDims;i++) { - if (debugout) TRACE_(olerelay)("[%d]",adesc->rgbounds[i].cElements); - arrsize *= adesc->rgbounds[i].cElements; - } - if (debugout) TRACE_(olerelay)("(vt %s)",debugstr_vt(adesc->tdescElem.vt)); - if (debugout) TRACE_(olerelay)("["); - for (i=0;i<arrsize;i++) { - LPBYTE base = _passbyref(&adesc->tdescElem, tinfo) ? (LPBYTE) *arg : (LPBYTE) arg; - hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)base+i*_xsize(&adesc->tdescElem, tinfo)), buf); - if (hres) - return hres; - if (debugout && (i<arrsize-1)) TRACE_(olerelay)(","); - } - if (debugout) TRACE_(olerelay)("]"); - if (dealloc) - HeapFree(GetProcessHeap(), 0, *(void **)arg); - return S_OK; - } - case VT_SAFEARRAY: { - if (writeit) - { - ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); - ULONG size = LPSAFEARRAY_UserSize(&flags, buf->curoff, (LPSAFEARRAY *)arg); - xbuf_resize(buf, size); - LPSAFEARRAY_UserMarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg); - buf->curoff = size; - } - if (dealloc) - { - ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); - LPSAFEARRAY_UserFree(&flags, (LPSAFEARRAY *)arg); - } - return S_OK; - } - default: - ERR("Unhandled marshal type %d.\n",tdesc->vt); - return S_OK; - } -} - -static HRESULT -deserialize_param( - ITypeInfo *tinfo, - BOOL readit, - BOOL debugout, - BOOL alloc, - TYPEDESC *tdesc, - DWORD *arg, - marshal_state *buf) -{ - HRESULT hres = S_OK; - VARTYPE vartype; - - TRACE("vt %s at %p\n",debugstr_vt(tdesc->vt),arg); - - vartype = tdesc->vt; - if ((vartype & 0xf000) == VT_ARRAY) - vartype = VT_SAFEARRAY; - - while (1) { - switch (vartype) { - case VT_VARIANT: { - if (readit) - { - ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); - unsigned char *buffer; - buffer = VARIANT_UserUnmarshal(&flags, buf->base + buf->curoff, (VARIANT *)arg); - buf->curoff = buffer - buf->base; - } - return S_OK; - } - case VT_DATE: - case VT_I8: - case VT_UI8: - case VT_R8: - case VT_CY: - if (readit) { - hres = xbuf_get(buf,(LPBYTE)arg,8); - if (hres) ERR("Failed to read integer 8 byte\n"); - } - if (debugout) TRACE_(olerelay)("%x%x",arg[0],arg[1]); - return hres; - case VT_ERROR: - case VT_I4: - case VT_INT: - case VT_UINT: - case VT_R4: - case VT_UI4: - if (readit) { - hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD)); - if (hres) ERR("Failed to read integer 4 byte\n"); - } - if (debugout) TRACE_(olerelay)("%x",*arg); - return hres; - case VT_I2: - case VT_UI2: - case VT_BOOL: - if (readit) { - DWORD x; - hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD)); - if (hres) ERR("Failed to read integer 4 byte\n"); - else memcpy(arg,&x,2); - } - if (debugout) TRACE_(olerelay)("%04x",*arg & 0xffff); - return hres; - case VT_I1: - case VT_UI1: - if (readit) { - DWORD x; - hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD)); - if (hres) ERR("Failed to read integer 4 byte\n"); - else memcpy(arg,&x,1); - } - if (debugout) TRACE_(olerelay)("%02x",*arg & 0xff); - return hres; - case VT_BSTR: { - if (readit) - { - ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); - unsigned char *buffer; - buffer = BSTR_UserUnmarshal(&flags, buf->base + buf->curoff, (BSTR *)arg); - buf->curoff = buffer - buf->base; - if (debugout) TRACE_(olerelay)("%s",debugstr_w(*(BSTR *)arg)); - } - return S_OK; - } - case VT_PTR: { - DWORD cookie; - BOOL derefhere = TRUE; - - if (tdesc->u.lptdesc->vt == VT_USERDEFINED) { - ITypeInfo *tinfo2; - TYPEATTR *tattr; - - hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2); - if (hres) { - ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype); - return hres; - } - ITypeInfo_GetTypeAttr(tinfo2,&tattr); - switch (tattr->typekind) { - case TKIND_ALIAS: - if (tattr->tdescAlias.vt == VT_USERDEFINED) - { - DWORD href = tattr->tdescAlias.u.hreftype; - ITypeInfo_ReleaseTypeAttr(tinfo, tattr); - ITypeInfo_Release(tinfo2); - hres = ITypeInfo_GetRefTypeInfo(tinfo,href,&tinfo2); - if (hres) { - ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype); - return hres; - } - ITypeInfo_GetTypeAttr(tinfo2,&tattr); - derefhere = (tattr->typekind != TKIND_DISPATCH && tattr->typekind != TKIND_INTERFACE); - } - break; - case TKIND_ENUM: /* confirmed */ - case TKIND_RECORD: /* FIXME: mostly untested */ - break; - case TKIND_DISPATCH: /* will be done in VT_USERDEFINED case */ - case TKIND_INTERFACE: /* will be done in VT_USERDEFINED case */ - derefhere=FALSE; - break; - default: - FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind); - derefhere=FALSE; - break; - } - ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); - ITypeInfo_Release(tinfo2); - } - /* read it in all cases, we need to know if we have - * NULL pointer or not. - */ - hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie)); - if (hres) { - ERR("Failed to load pointer cookie.\n"); - return hres; - } - if (cookie != 0x42424242) { - /* we read a NULL ptr from the remote side */ - if (debugout) TRACE_(olerelay)("NULL"); - *arg = 0; - return S_OK; - } - if (debugout) TRACE_(olerelay)("*"); - if (alloc) { - /* Allocate space for the referenced struct */ - if (derefhere) - *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc, tinfo)); - } - if (derefhere) - return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, (LPDWORD)*arg, buf); - else - return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, arg, buf); - } - case VT_UNKNOWN: - /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */ - if (alloc) - *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)); - hres = S_OK; - if (readit) - hres = _unmarshal_interface(buf,&IID_IUnknown,(LPUNKNOWN*)arg); - if (debugout) - TRACE_(olerelay)("unk(%p)",arg); - return hres; - case VT_DISPATCH: - hres = S_OK; - if (readit) - hres = _unmarshal_interface(buf,&IID_IDispatch,(LPUNKNOWN*)arg); - if (debugout) - TRACE_(olerelay)("idisp(%p)",arg); - return hres; - case VT_VOID: - if (debugout) TRACE_(olerelay)("<void>"); - return S_OK; - case VT_USERDEFINED: { - ITypeInfo *tinfo2; - TYPEATTR *tattr; - - hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); - if (hres) { - ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype); - return hres; - } - hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr); - if (hres) { - ERR("Could not get typeattr in VT_USERDEFINED.\n"); - } else { - switch (tattr->typekind) { - case TKIND_DISPATCH: - case TKIND_INTERFACE: - if (readit) - hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg); - break; - case TKIND_RECORD: { - int i; - - if (debugout) TRACE_(olerelay)("{"); - for (i=0;i<tattr->cVars;i++) { - VARDESC *vdesc; - - hres = ITypeInfo_GetVarDesc(tinfo2, i, &vdesc); - if (hres) { - ERR("Could not get vardesc of %d\n",i); - ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); - ITypeInfo_Release(tinfo2); - return hres; - } - hres = deserialize_param( - tinfo2, - readit, - debugout, - alloc, - &vdesc->elemdescVar.tdesc, - (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst), - buf - ); - ITypeInfo_ReleaseVarDesc(tinfo2, vdesc); - if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(","); - } - if (debugout) TRACE_(olerelay)("}"); - break; - } - case TKIND_ALIAS: - hres = deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf); - break; - case TKIND_ENUM: - if (readit) { - hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD)); - if (hres) ERR("Failed to read enum (4 byte)\n"); - } - if (debugout) TRACE_(olerelay)("%x",*arg); - break; - default: - ERR("Unhandled typekind %d\n",tattr->typekind); - hres = E_FAIL; - break; - } - ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); - } - if (hres) - ERR("failed to stuballoc in TKIND_RECORD.\n"); - ITypeInfo_Release(tinfo2); - return hres; - } - case VT_CARRAY: { - /* arg is pointing to the start of the array. */ - LPBYTE base = (LPBYTE) arg; - ARRAYDESC *adesc = tdesc->u.lpadesc; - int arrsize,i; - arrsize = 1; - if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n"); - for (i=0;i<adesc->cDims;i++) - arrsize *= adesc->rgbounds[i].cElements; - if (_passbyref(&adesc->tdescElem, tinfo)) - { - base = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc, tinfo) * arrsize); - *arg = (DWORD) base; - } - for (i=0;i<arrsize;i++) - deserialize_param( - tinfo, - readit, - debugout, - alloc, - &adesc->tdescElem, - (DWORD*)(base + i*_xsize(&adesc->tdescElem, tinfo)), - buf - ); - return S_OK; - } - case VT_SAFEARRAY: { - if (readit) - { - ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); - unsigned char *buffer; - buffer = LPSAFEARRAY_UserUnmarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg); - buf->curoff = buffer - buf->base; - } - return S_OK; - } - default: - ERR("No handler for VT type %d!\n",tdesc->vt); - return S_OK; - } - } -} - -/* Retrieves a function's funcdesc, searching back into inherited interfaces. */ -static HRESULT get_funcdesc(ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc, - BSTR *iname, BSTR *fname, UINT *num) -{ - HRESULT hr; - UINT i, impl_types; - UINT inherited_funcs = 0; - TYPEATTR *attr; - - if (fname) *fname = NULL; - if (iname) *iname = NULL; - if (num) *num = 0; - *tactual = NULL; - - hr = ITypeInfo_GetTypeAttr(tinfo, &attr); - if (FAILED(hr)) - { - 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); - - for (i = 0; i < impl_types; i++) - { - HREFTYPE href; - ITypeInfo *pSubTypeInfo; - UINT sub_funcs; - - hr = ITypeInfo_GetRefTypeOfImplType(tinfo, i, &href); - if (FAILED(hr)) return hr; - hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &pSubTypeInfo); - if (FAILED(hr)) return hr; - - hr = get_funcdesc(pSubTypeInfo, iMethod, tactual, fdesc, iname, fname, &sub_funcs); - inherited_funcs += sub_funcs; - ITypeInfo_Release(pSubTypeInfo); - if(SUCCEEDED(hr)) return hr; - } - if(iMethod < inherited_funcs) - { - ERR("shouldn't be here\n"); - return E_INVALIDARG; - } - - for(i = inherited_funcs; i <= iMethod; i++) - { - hr = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i - inherited_funcs, fdesc); - if(FAILED(hr)) - { - if(num) *num = i; - return hr; - } - } - - /* found it. We don't care about num so zero it */ - if(num) *num = 0; - *tactual = tinfo; - ITypeInfo_AddRef(*tactual); - if (fname) ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL); - if (iname) ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL); - return S_OK; -} - -static inline BOOL is_in_elem(const ELEMDESC *elem) -{ - return (elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags); -} - -static inline BOOL is_out_elem(const ELEMDESC *elem) -{ - return (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT || !elem->u.paramdesc.wParamFlags); -} - -static DWORD WINAPI xCall(int method, void **args) -{ - TMProxyImpl *tpinfo = args[0]; - DWORD *xargs; - const FUNCDESC *fdesc; - HRESULT hres; - int i; - marshal_state buf; - RPCOLEMESSAGE msg; - ULONG status; - BSTR fname,iname; - BSTR names[10]; - UINT nrofnames; - DWORD remoteresult = 0; - ITypeInfo *tinfo; - IRpcChannelBuffer *chanbuf; - - EnterCriticalSection(&tpinfo->crit); - - hres = get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname,NULL); - if (hres) { - ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method); - LeaveCriticalSection(&tpinfo->crit); - return E_FAIL; - } - - if (!tpinfo->chanbuf) - { - WARN("Tried to use disconnected proxy\n"); - ITypeInfo_Release(tinfo); - LeaveCriticalSection(&tpinfo->crit); - return RPC_E_DISCONNECTED; - } - chanbuf = tpinfo->chanbuf; - IRpcChannelBuffer_AddRef(chanbuf); - - LeaveCriticalSection(&tpinfo->crit); - - if (TRACE_ON(olerelay)) { - TRACE_(olerelay)("->"); - if (iname) - TRACE_(olerelay)("%s:",relaystr(iname)); - if (fname) - TRACE_(olerelay)("%s(%d)",relaystr(fname),method); - else - TRACE_(olerelay)("%d",method); - TRACE_(olerelay)("("); - } - - SysFreeString(iname); - SysFreeString(fname); - - memset(&buf,0,sizeof(buf)); - - /* normal typelib driven serializing */ - - /* Need them for hack below */ - memset(names,0,sizeof(names)); - if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,ARRAY_SIZE(names),&nrofnames)) - nrofnames = 0; - if (nrofnames > ARRAY_SIZE(names)) - ERR("Need more names!\n"); - - xargs = (DWORD *)(args + 1); - for (i=0;i<fdesc->cParams;i++) { - ELEMDESC *elem = fdesc->lprgelemdescParam+i; - if (TRACE_ON(olerelay)) { - if (i) TRACE_(olerelay)(","); - if (i+1<nrofnames && names[i+1]) - TRACE_(olerelay)("%s=",relaystr(names[i+1])); - } - /* No need to marshal other data than FIN and any VT_PTR. */ - if (!is_in_elem(elem)) - { - if (elem->tdesc.vt != VT_PTR) - { - xargs+=_argsize(&elem->tdesc, tinfo); - TRACE_(olerelay)("[out]"); - continue; - } - else - { - memset( *(void **)xargs, 0, _xsize( elem->tdesc.u.lptdesc, tinfo ) ); - } - } - - hres = serialize_param( - tinfo, - is_in_elem(elem), - TRACE_ON(olerelay), - FALSE, - &elem->tdesc, - xargs, - &buf - ); - - if (hres) { - ERR("Failed to serialize param, hres %x\n",hres); - break; - } - xargs+=_argsize(&elem->tdesc, tinfo); - } - TRACE_(olerelay)(")"); - - memset(&msg,0,sizeof(msg)); - msg.cbBuffer = buf.curoff; - msg.iMethod = method; - hres = IRpcChannelBuffer_GetBuffer(chanbuf,&msg,&(tpinfo->iid)); - if (hres) { - ERR("RpcChannelBuffer GetBuffer failed, %x\n",hres); - goto exit; - } - memcpy(msg.Buffer,buf.base,buf.curoff); - TRACE_(olerelay)("\n"); - hres = IRpcChannelBuffer_SendReceive(chanbuf,&msg,&status); - if (hres) { - ERR("RpcChannelBuffer SendReceive failed, %x\n",hres); - goto exit; - } - - TRACE_(olerelay)(" status = %08x (",status); - if (buf.base) - buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer); - else - buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer); - buf.size = msg.cbBuffer; - memcpy(buf.base,msg.Buffer,buf.size); - buf.curoff = 0; - - /* generic deserializer using typelib description */ - xargs = (DWORD *)(args + 1); - status = S_OK; - for (i=0;i<fdesc->cParams;i++) { - ELEMDESC *elem = fdesc->lprgelemdescParam+i; - - if (i) TRACE_(olerelay)(","); - if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1])); - - /* No need to marshal other data than FOUT and any VT_PTR */ - if (!is_out_elem(elem) && (elem->tdesc.vt != VT_PTR)) { - xargs += _argsize(&elem->tdesc, tinfo); - TRACE_(olerelay)("[in]"); - continue; - } - hres = deserialize_param( - tinfo, - is_out_elem(elem), - TRACE_ON(olerelay), - FALSE, - &(elem->tdesc), - xargs, - &buf - ); - if (hres) { - ERR("Failed to unmarshall param, hres %x\n",hres); - status = hres; - break; - } - xargs += _argsize(&elem->tdesc, tinfo); - } - - hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD)); - if (hres != S_OK) - goto exit; - TRACE_(olerelay)(") = %08x\n", remoteresult); - - hres = remoteresult; - -exit: - IRpcChannelBuffer_FreeBuffer(chanbuf,&msg); - for (i = 0; i < nrofnames; i++) - SysFreeString(names[i]); - HeapFree(GetProcessHeap(),0,buf.base); - IRpcChannelBuffer_Release(chanbuf); - ITypeInfo_Release(tinfo); - TRACE("-- 0x%08x\n", hres); - return hres; -} - -static HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) -{ - TMProxyImpl *proxy = (TMProxyImpl *)iface; - - TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); - - if (proxy->outerunknown) - return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv); - - FIXME("No interface\n"); - return E_NOINTERFACE; -} - -static ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface) -{ - TMProxyImpl *proxy = (TMProxyImpl *)iface; - - TRACE("\n"); - - if (proxy->outerunknown) - return IUnknown_AddRef(proxy->outerunknown); - - return 2; /* FIXME */ -} - -static ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface) -{ - TMProxyImpl *proxy = (TMProxyImpl *)iface; - - TRACE("\n"); - - if (proxy->outerunknown) - return IUnknown_Release(proxy->outerunknown); - - return 1; /* FIXME */ -} - -static HRESULT WINAPI ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo) -{ - TMProxyImpl *This = (TMProxyImpl *)iface; - - TRACE("(%p)\n", pctinfo); - - return IDispatch_GetTypeInfoCount(This->dispatch, pctinfo); -} - -static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) -{ - TMProxyImpl *This = (TMProxyImpl *)iface; - - TRACE("(%d, %x, %p)\n", iTInfo, lcid, ppTInfo); - - return IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo); -} - -static HRESULT WINAPI ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) -{ - TMProxyImpl *This = (TMProxyImpl *)iface; - - TRACE("(%s, %p, %d, 0x%x, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); - - return IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames, - cNames, lcid, rgDispId); -} - -static HRESULT WINAPI ProxyIDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid, - WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult, - EXCEPINFO * pExcepInfo, UINT * puArgErr) -{ - TMProxyImpl *This = (TMProxyImpl *)iface; - - TRACE("(%d, %s, 0x%x, 0x%x, %p, %p, %p, %p)\n", dispIdMember, - debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, - pExcepInfo, puArgErr); - - return IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid, - wFlags, pDispParams, pVarResult, pExcepInfo, - puArgErr); -} - -typedef struct -{ - IRpcChannelBuffer IRpcChannelBuffer_iface; - LONG refs; - /* the IDispatch-derived interface we are handling */ - IID tmarshal_iid; - IRpcChannelBuffer *pDelegateChannel; -} TMarshalDispatchChannel; - -static inline TMarshalDispatchChannel *impl_from_IRpcChannelBuffer(IRpcChannelBuffer *iface) -{ - return CONTAINING_RECORD(iface, TMarshalDispatchChannel, IRpcChannelBuffer_iface); -} - -static HRESULT WINAPI TMarshalDispatchChannel_QueryInterface(IRpcChannelBuffer *iface, REFIID riid, LPVOID *ppv) -{ - *ppv = NULL; - if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown)) - { - *ppv = iface; - IRpcChannelBuffer_AddRef(iface); - return S_OK; - } - return E_NOINTERFACE; -} - -static ULONG WINAPI TMarshalDispatchChannel_AddRef(LPRPCCHANNELBUFFER iface) -{ - TMarshalDispatchChannel *This = impl_from_IRpcChannelBuffer(iface); - return InterlockedIncrement(&This->refs); -} - -static ULONG WINAPI TMarshalDispatchChannel_Release(LPRPCCHANNELBUFFER iface) -{ - TMarshalDispatchChannel *This = impl_from_IRpcChannelBuffer(iface); - ULONG ref; - - ref = InterlockedDecrement(&This->refs); - if (ref) - return ref; - - IRpcChannelBuffer_Release(This->pDelegateChannel); - HeapFree(GetProcessHeap(), 0, This); - return 0; -} - -static HRESULT WINAPI TMarshalDispatchChannel_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid) -{ - TMarshalDispatchChannel *This = impl_from_IRpcChannelBuffer(iface); - TRACE("(%p, %s)\n", olemsg, debugstr_guid(riid)); - /* Note: we are pretending to invoke a method on the interface identified - * by tmarshal_iid so that we can re-use the IDispatch proxy/stub code - * without the RPC runtime getting confused by not exporting an IDispatch interface */ - return IRpcChannelBuffer_GetBuffer(This->pDelegateChannel, olemsg, &This->tmarshal_iid); -} - -static HRESULT WINAPI TMarshalDispatchChannel_SendReceive(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE *olemsg, ULONG *pstatus) -{ - TMarshalDispatchChannel *This = impl_from_IRpcChannelBuffer(iface); - TRACE("(%p, %p)\n", olemsg, pstatus); - return IRpcChannelBuffer_SendReceive(This->pDelegateChannel, olemsg, pstatus); -} - -static HRESULT WINAPI TMarshalDispatchChannel_FreeBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg) -{ - TMarshalDispatchChannel *This = impl_from_IRpcChannelBuffer(iface); - TRACE("(%p)\n", olemsg); - return IRpcChannelBuffer_FreeBuffer(This->pDelegateChannel, olemsg); -} - -static HRESULT WINAPI TMarshalDispatchChannel_GetDestCtx(LPRPCCHANNELBUFFER iface, DWORD* pdwDestContext, void** ppvDestContext) -{ - TMarshalDispatchChannel *This = impl_from_IRpcChannelBuffer(iface); - TRACE("(%p,%p)\n", pdwDestContext, ppvDestContext); - return IRpcChannelBuffer_GetDestCtx(This->pDelegateChannel, pdwDestContext, ppvDestContext); -} - -static HRESULT WINAPI TMarshalDispatchChannel_IsConnected(LPRPCCHANNELBUFFER iface) -{ - TMarshalDispatchChannel *This = impl_from_IRpcChannelBuffer(iface); - TRACE("()\n"); - return IRpcChannelBuffer_IsConnected(This->pDelegateChannel); -} - -static const IRpcChannelBufferVtbl TMarshalDispatchChannelVtbl = -{ - TMarshalDispatchChannel_QueryInterface, - TMarshalDispatchChannel_AddRef, - TMarshalDispatchChannel_Release, - TMarshalDispatchChannel_GetBuffer, - TMarshalDispatchChannel_SendReceive, - TMarshalDispatchChannel_FreeBuffer, - TMarshalDispatchChannel_GetDestCtx, - TMarshalDispatchChannel_IsConnected -}; - -static HRESULT TMarshalDispatchChannel_Create( - IRpcChannelBuffer *pDelegateChannel, REFIID tmarshal_riid, - IRpcChannelBuffer **ppChannel) -{ - TMarshalDispatchChannel *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); - if (!This) - return E_OUTOFMEMORY; - - This->IRpcChannelBuffer_iface.lpVtbl = &TMarshalDispatchChannelVtbl; - This->refs = 1; - IRpcChannelBuffer_AddRef(pDelegateChannel); - This->pDelegateChannel = pDelegateChannel; - This->tmarshal_iid = *tmarshal_riid; - - *ppChannel = &This->IRpcChannelBuffer_iface; - return S_OK; -} - - -static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf) -{ - HRESULT hr; - CLSID clsid; - - if ((hr = CoGetPSClsid(riid, &clsid))) - return hr; - return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, - &IID_IPSFactoryBuffer, (LPVOID*)facbuf); -} - -static HRESULT init_proxy_entry_point(TMProxyImpl *proxy, unsigned int num) -{ - int j; - /* nrofargs including This */ - int nrofargs = 1; - ITypeInfo *tinfo2; - TMAsmProxy *xasm = proxy->asmstubs + num; - HRESULT hres; - const FUNCDESC *fdesc; - - hres = get_funcdesc(proxy->tinfo, num, &tinfo2, &fdesc, NULL, NULL, NULL); - if (hres) { - ERR("GetFuncDesc %x should not fail here.\n",hres); - return hres; - } - ITypeInfo_Release(tinfo2); - /* some args take more than 4 byte on the stack */ - for (j=0;j<fdesc->cParams;j++) - nrofargs += _argsize(&fdesc->lprgelemdescParam[j].tdesc, proxy->tinfo); - -#ifdef __i386__ - if (fdesc->callconv != CC_STDCALL) { - ERR("calling convention is not stdcall????\n"); - return E_FAIL; - } -/* leal 4(%esp),%eax - * pushl %eax - * pushl <nr> - * call xCall - * lret <nr> - */ - xasm->lealeax = 0x0424448d; - xasm->pushleax = 0x50; - xasm->pushlval = 0x68; - xasm->nr = num; - xasm->lcall = 0xe8; - xasm->xcall = (char *)xCall - (char *)&xasm->lret; - xasm->lret = 0xc2; - xasm->bytestopop = nrofargs * 4; - xasm->nop = 0x9090; - proxy->lpvtbl[fdesc->oVft / sizeof(void *)] = xasm; -#else - FIXME("not implemented on non i386\n"); - return E_FAIL; -#endif - return S_OK; -} - -static HRESULT WINAPI -PSFacBuf_CreateProxy( - LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid, - IRpcProxyBuffer **ppProxy, LPVOID *ppv) -{ - HRESULT hres; - ITypeInfo *tinfo; - unsigned int i, nroffuncs, vtbl_size; - TMProxyImpl *proxy; - TYPEATTR *typeattr; - BOOL defer_to_dispatch = FALSE; - - TRACE("(...%s...)\n",debugstr_guid(riid)); - hres = _get_typeinfo_for_iid(riid,&tinfo); - if (hres) { - ERR("No typeinfo for %s?\n",debugstr_guid(riid)); - return hres; - } - - hres = num_of_funcs(tinfo, &nroffuncs, &vtbl_size); - TRACE("Got %d funcs, vtbl size %d\n", nroffuncs, vtbl_size); - - 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; - - proxy->dispatch = NULL; - proxy->dispatch_proxy = NULL; - proxy->outerunknown = pUnkOuter; - proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE); - if (!proxy->asmstubs) { - ERR("Could not commit pages for proxy thunks\n"); - CoTaskMemFree(proxy); - return E_OUTOFMEMORY; - } - proxy->IRpcProxyBuffer_iface.lpVtbl = &tmproxyvtable; - /* one reference for the proxy */ - proxy->ref = 1; - proxy->tinfo = tinfo; - proxy->iid = *riid; - proxy->chanbuf = 0; - - InitializeCriticalSection(&proxy->crit); - proxy->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TMProxyImpl.crit"); - - proxy->lpvtbl = HeapAlloc(GetProcessHeap(), 0, vtbl_size); - - /* if we derive from IDispatch then defer to its proxy for its methods */ - hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr); - if (hres == S_OK) - { - if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) - { - IPSFactoryBuffer *factory_buffer; - hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer); - if (hres == S_OK) - { - hres = IPSFactoryBuffer_CreateProxy(factory_buffer, NULL, - &IID_IDispatch, &proxy->dispatch_proxy, - (void **)&proxy->dispatch); - IPSFactoryBuffer_Release(factory_buffer); - } - if ((hres == S_OK) && (nroffuncs < 7)) - { - ERR("nroffuncs calculated incorrectly (%d)\n", nroffuncs); - hres = E_UNEXPECTED; - } - if (hres == S_OK) - { - 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); - else proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount; - break; - case 4: - if(!defer_to_dispatch) hres = init_proxy_entry_point(proxy, i); - else proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo; - break; - case 5: - if(!defer_to_dispatch) hres = init_proxy_entry_point(proxy, i); - else proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames; - break; - case 6: - if(!defer_to_dispatch) hres = init_proxy_entry_point(proxy, i); - else proxy->lpvtbl[6] = ProxyIDispatch_Invoke; - break; - default: - hres = init_proxy_entry_point(proxy, i); - } - } - - if (hres == S_OK) - { - *ppv = proxy; - *ppProxy = &proxy->IRpcProxyBuffer_iface; - IUnknown_AddRef((IUnknown *)*ppv); - return S_OK; - } - else - TMProxyImpl_Release(&proxy->IRpcProxyBuffer_iface); - return hres; -} - -typedef struct _TMStubImpl { - IRpcStubBuffer IRpcStubBuffer_iface; - LONG ref; - - LPUNKNOWN pUnk; - ITypeInfo *tinfo; - IID iid; - IRpcStubBuffer *dispatch_stub; - BOOL dispatch_derivative; -} TMStubImpl; - -static inline TMStubImpl *impl_from_IRpcStubBuffer(IRpcStubBuffer *iface) -{ - return CONTAINING_RECORD(iface, TMStubImpl, IRpcStubBuffer_iface); -} - -static HRESULT WINAPI -TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv) -{ - if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){ - *ppv = iface; - IRpcStubBuffer_AddRef(iface); - return S_OK; - } - FIXME("%s, not supported IID.\n",debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI -TMStubImpl_AddRef(LPRPCSTUBBUFFER iface) -{ - TMStubImpl *This = impl_from_IRpcStubBuffer(iface); - ULONG refCount = InterlockedIncrement(&This->ref); - - TRACE("(%p)->(ref before=%u)\n", This, refCount - 1); - - return refCount; -} - -static ULONG WINAPI -TMStubImpl_Release(LPRPCSTUBBUFFER iface) -{ - TMStubImpl *This = impl_from_IRpcStubBuffer(iface); - ULONG refCount = InterlockedDecrement(&This->ref); - - TRACE("(%p)->(ref before=%u)\n", This, refCount + 1); - - if (!refCount) - { - IRpcStubBuffer_Disconnect(iface); - ITypeInfo_Release(This->tinfo); - if (This->dispatch_stub) - IRpcStubBuffer_Release(This->dispatch_stub); - CoTaskMemFree(This); - } - return refCount; -} - -static HRESULT WINAPI -TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer) -{ - TMStubImpl *This = impl_from_IRpcStubBuffer(iface); - - TRACE("(%p)->(%p)\n", This, pUnkServer); - - IUnknown_AddRef(pUnkServer); - This->pUnk = pUnkServer; - - if (This->dispatch_stub) - IRpcStubBuffer_Connect(This->dispatch_stub, pUnkServer); - - return S_OK; -} - -static void WINAPI -TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface) -{ - TMStubImpl *This = impl_from_IRpcStubBuffer(iface); - - TRACE("(%p)->()\n", This); - - if (This->pUnk) - { - IUnknown_Release(This->pUnk); - This->pUnk = NULL; - } - - if (This->dispatch_stub) - IRpcStubBuffer_Disconnect(This->dispatch_stub); -} - -static HRESULT WINAPI -TMStubImpl_Invoke( - LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf) -{ -#ifdef __i386__ - int i; - const FUNCDESC *fdesc; - TMStubImpl *This = impl_from_IRpcStubBuffer(iface); - HRESULT hres; - DWORD *args = NULL, res, *xargs, nrofargs; - marshal_state buf; - UINT nrofnames = 0; - BSTR names[10]; - BSTR iname = NULL; - ITypeInfo *tinfo = NULL; - - TRACE("...\n"); - - if (xmsg->iMethod < 3) { - ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n"); - return E_UNEXPECTED; - } - - if (This->dispatch_derivative && xmsg->iMethod < sizeof(IDispatchVtbl)/sizeof(void *)) - { - if (!This->dispatch_stub) - { - IPSFactoryBuffer *factory_buffer; - hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer); - if (hres == S_OK) - { - hres = IPSFactoryBuffer_CreateStub(factory_buffer, &IID_IDispatch, - This->pUnk, &This->dispatch_stub); - IPSFactoryBuffer_Release(factory_buffer); - } - if (hres != S_OK) - return hres; - } - return IRpcStubBuffer_Invoke(This->dispatch_stub, xmsg, rpcchanbuf); - } - - memset(&buf,0,sizeof(buf)); - buf.size = xmsg->cbBuffer; - buf.base = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer); - memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer); - buf.curoff = 0; - - hres = get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL,NULL); - if (hres) { - ERR("GetFuncDesc on method %d failed with %x\n",xmsg->iMethod,hres); - return hres; - } - - if (iname && !lstrcmpW(iname, IDispatchW)) - { - ERR("IDispatch cannot be marshaled by the typelib marshaler\n"); - hres = E_UNEXPECTED; - SysFreeString (iname); - goto exit; - } - - SysFreeString (iname); - - /* Need them for hack below */ - memset(names,0,sizeof(names)); - ITypeInfo_GetNames(tinfo,fdesc->memid,names,ARRAY_SIZE(names),&nrofnames); - if (nrofnames > ARRAY_SIZE(names)) { - ERR("Need more names!\n"); - } - - /*dump_FUNCDESC(fdesc);*/ - nrofargs = 0; - for (i=0;i<fdesc->cParams;i++) - nrofargs += _argsize(&fdesc->lprgelemdescParam[i].tdesc, tinfo); - args = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(nrofargs+1)*sizeof(DWORD)); - if (!args) - { - hres = E_OUTOFMEMORY; - goto exit; - } - - /* Allocate all stuff used by call. */ - xargs = args+1; - for (i=0;i<fdesc->cParams;i++) { - ELEMDESC *elem = fdesc->lprgelemdescParam+i; - - hres = deserialize_param( - tinfo, - is_in_elem(elem), - FALSE, - TRUE, - &(elem->tdesc), - xargs, - &buf - ); - xargs += _argsize(&elem->tdesc, tinfo); - if (hres) { - ERR("Failed to deserialize param %s, hres %x\n",relaystr(names[i+1]),hres); - break; - } - } - - args[0] = (DWORD)This->pUnk; - - __TRY - { - res = _invoke( - (*((FARPROC**)args[0]))[fdesc->oVft/4], - fdesc->callconv, - (xargs-args), - args - ); - } - __EXCEPT_ALL - { - DWORD dwExceptionCode = GetExceptionCode(); - ERR("invoke call failed with exception 0x%08x (%d)\n", dwExceptionCode, dwExceptionCode); - if (FAILED(dwExceptionCode)) - hres = dwExceptionCode; - else - hres = HRESULT_FROM_WIN32(dwExceptionCode); - } - __ENDTRY - - if (hres != S_OK) - goto exit; - - buf.curoff = 0; - - xargs = args+1; - for (i=0;i<fdesc->cParams;i++) { - ELEMDESC *elem = fdesc->lprgelemdescParam+i; - hres = serialize_param( - tinfo, - is_out_elem(elem), - FALSE, - TRUE, - &elem->tdesc, - xargs, - &buf - ); - xargs += _argsize(&elem->tdesc, tinfo); - if (hres) { - ERR("Failed to stuballoc param, hres %x\n",hres); - break; - } - } - - hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD)); - - if (hres != S_OK) - goto exit; - - xmsg->cbBuffer = buf.curoff; - hres = IRpcChannelBuffer_GetBuffer(rpcchanbuf, xmsg, &This->iid); - if (hres != S_OK) - ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08x\n", hres); - - if (hres == S_OK) - memcpy(xmsg->Buffer, buf.base, buf.curoff); - -exit: - for (i = 0; i < nrofnames; i++) - SysFreeString(names[i]); - - ITypeInfo_Release(tinfo); - HeapFree(GetProcessHeap(), 0, args); - - HeapFree(GetProcessHeap(), 0, buf.base); - - TRACE("returning\n"); - return hres; -#else - FIXME( "not implemented on non-i386\n" ); - return E_FAIL; -#endif -} - -static LPRPCSTUBBUFFER WINAPI -TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) { - FIXME("Huh (%s)?\n",debugstr_guid(riid)); - return NULL; -} - -static ULONG WINAPI -TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) { - TMStubImpl *This = impl_from_IRpcStubBuffer(iface); - - FIXME("()\n"); - return This->ref; /*FIXME? */ -} - -static HRESULT WINAPI -TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) { - return E_NOTIMPL; -} - -static void WINAPI -TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) { - return; -} - -static const IRpcStubBufferVtbl tmstubvtbl = { - TMStubImpl_QueryInterface, - TMStubImpl_AddRef, - TMStubImpl_Release, - TMStubImpl_Connect, - TMStubImpl_Disconnect, - TMStubImpl_Invoke, - TMStubImpl_IsIIDSupported, - TMStubImpl_CountRefs, - TMStubImpl_DebugServerQueryInterface, - TMStubImpl_DebugServerRelease -}; - -static HRESULT WINAPI -PSFacBuf_CreateStub( - LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer, - IRpcStubBuffer** ppStub -) { - HRESULT hres; - ITypeInfo *tinfo; - TMStubImpl *stub; - TYPEATTR *typeattr; - IUnknown *obj; - - TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub); - - hres = _get_typeinfo_for_iid(riid,&tinfo); - if (hres) { - ERR("No typeinfo for %s?\n",debugstr_guid(riid)); - return hres; - } - - /* FIXME: This is not exactly right. We should probably call QI later. */ - hres = IUnknown_QueryInterface(pUnkServer, riid, (void**)&obj); - if (FAILED(hres)) { - WARN("Could not get %s iface: %08x\n", debugstr_guid(riid), hres); - obj = pUnkServer; - IUnknown_AddRef(obj); - } - - stub = CoTaskMemAlloc(sizeof(TMStubImpl)); - if (!stub) { - IUnknown_Release(obj); - return E_OUTOFMEMORY; - } - stub->IRpcStubBuffer_iface.lpVtbl = &tmstubvtbl; - stub->ref = 1; - stub->tinfo = tinfo; - stub->dispatch_stub = NULL; - stub->dispatch_derivative = FALSE; - stub->iid = *riid; - hres = IRpcStubBuffer_Connect(&stub->IRpcStubBuffer_iface, obj); - *ppStub = &stub->IRpcStubBuffer_iface; - TRACE("IRpcStubBuffer: %p\n", stub); - if (hres) - ERR("Connect to pUnkServer failed?\n"); - - /* if we derive from IDispatch then defer to its stub for some of its methods */ - hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr); - if (hres == S_OK) - { - if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) - stub->dispatch_derivative = TRUE; - ITypeInfo_ReleaseTypeAttr(tinfo, typeattr); - } - - IUnknown_Release(obj); - return hres; -} - -static const IPSFactoryBufferVtbl psfacbufvtbl = { - PSFacBuf_QueryInterface, - PSFacBuf_AddRef, - PSFacBuf_Release, - PSFacBuf_CreateProxy, - PSFacBuf_CreateStub -}; - -static IPSFactoryBuffer psfac = { &psfacbufvtbl }; - -/*********************************************************************** - * TMARSHAL_DllGetClassObject - */ -HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid, void **ppv) -{ - return IPSFactoryBuffer_QueryInterface(&psfac, iid, ppv); -} diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 2c0a519679..4555802a61 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -6345,38 +6345,6 @@ __ASM_GLOBAL_FUNC( call_method, __ASM_GLOBAL_FUNC( call_double_method, "jmp " __ASM_NAME("call_method") )
-/* ITypeInfo::Invoke - * - * Invokes a method, or accesses a property of an object, that implements the - * interface described by the type description. - */ -DWORD -_invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) { - DWORD res; - int stack_offset; - - if (TRACE_ON(ole)) { - int i; - TRACE("Calling %p(",func); - for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]); - if (nrargs > 30) TRACE("..."); - TRACE(")\n"); - } - - switch (callconv) { - case CC_STDCALL: - case CC_CDECL: - res = call_method( func, nrargs, args, &stack_offset ); - break; - default: - FIXME("unsupported calling convention %d\n",callconv); - res = -1; - break; - } - TRACE("returns %08x\n",res); - return res; -} - #elif defined(__x86_64__)
extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args ); diff --git a/dlls/oleaut32/typelib.h b/dlls/oleaut32/typelib.h index 629ed72ae0..71e8d080c4 100644 --- a/dlls/oleaut32/typelib.h +++ b/dlls/oleaut32/typelib.h @@ -595,12 +595,6 @@ WORD typeofarray
#include "poppack.h"
-HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc ) DECLSPEC_HIDDEN; - -extern DWORD _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) DECLSPEC_HIDDEN; - -HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) DECLSPEC_HIDDEN; - /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */ DEFINE_OLEGUID( CLSID_PSDispatch, 0x00020420, 0x0000, 0x0000 ); DEFINE_OLEGUID( CLSID_PSEnumVariant, 0x00020421, 0x0000, 0x0000 );