From 077b4391d442e927a2a59b5afb244355b0634aaa Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 9 Nov 2018 18:02:00 -0600 Subject: [PATCH] oleaut32: Rip out the old typelib marshaller. Signed-off-by: Zebediah Figura Signed-off-by: Marcus Meissner Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/oleaut32/Makefile.in | 1 - dlls/oleaut32/oleaut.c | 284 +++- dlls/oleaut32/tests/tmarshal.c | 26 - dlls/oleaut32/tmarshal.c | 2351 -------------------------------- dlls/oleaut32/typelib.c | 32 - dlls/oleaut32/typelib.h | 6 - 6 files changed, 255 insertions(+), 2445 deletions(-) delete mode 100644 dlls/oleaut32/tmarshal.c diff --git a/dlls/oleaut32/Makefile.in b/dlls/oleaut32/Makefile.in index 4c9d1d2ef15..a7dea7a37c7 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 a12b45ec338..3161d5e1ddf 100644 --- a/dlls/oleaut32/oleaut.c +++ b/dlls/oleaut32/oleaut.c @@ -21,6 +21,7 @@ #include "config.h" #include +#include #include #include @@ -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); + if (IsEqualIID(iid, &IID_IDispatch)) + { + hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory); + if (FAILED(hr)) return hr; + + hr = IPSFactoryBuffer_CreateProxy(factory, outer, iid, proxy, obj); + IPSFactoryBuffer_Release(factory); + return hr; + } else - hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB); - - if (FAILED(hr)) return hr; - - hr = IPSFactoryBuffer_CreateProxy(pPSFB, pUnkOuter, riid, ppProxy, ppv); - - IPSFactoryBuffer_Release(pPSFB); - return hr; + 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); + if (IsEqualIID(iid, &IID_IDispatch)) + { + hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory); + if (FAILED(hr)) return hr; + + hr = IPSFactoryBuffer_CreateStub(factory, iid, server, stub); + IPSFactoryBuffer_Release(factory); + return hr; + } else - hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB); - - if (FAILED(hr)) return hr; - - hr = IPSFactoryBuffer_CreateStub(pPSFB, riid, pUnkOuter, ppStub); - - IPSFactoryBuffer_Release(pPSFB); - return hr; + 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 c92e208795e..4049d195e0a 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,9 +2384,6 @@ static void test_typelibmarshal(void) IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW); -#ifndef __i386__ - todo_wine -#endif ok_ole_success(hr, CoUnmarshalInterface); IStream_Release(pStream); if (FAILED(hr)) @@ -3080,9 +3057,6 @@ static void test_external_connection(void) IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface); -#ifndef __i386__ - todo_wine -#endif ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres); if (FAILED(hres)) { diff --git a/dlls/oleaut32/tmarshal.c b/dlls/oleaut32/tmarshal.c deleted file mode 100644 index 1e1688e690a..00000000000 --- 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 -#include -#include -#include -#include -#include - -#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;icDims;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)(""); - } - 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)(""); - 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;icVars;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;icDims;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;itdescElem, 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 && (icuroff, (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)(""); - 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;icVars;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 && (icVars-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;icDims;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;itdescElem, - (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;icParams;i++) { - ELEMDESC *elem = fdesc->lprgelemdescParam+i; - if (TRACE_ON(olerelay)) { - if (i) TRACE_(olerelay)(","); - if (i+1tdesc.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;icParams;i++) { - ELEMDESC *elem = fdesc->lprgelemdescParam+i; - - if (i) TRACE_(olerelay)(","); - if (i+1tdesc), - 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;jcParams;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 - * call xCall - * lret - */ - 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;ilpvtbl[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;icParams;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;icParams;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;icParams;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 2c0a5196798..4555802a612 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 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 629ed72ae04..71e8d080c44 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 );