-/*\r
- * TYPELIB Marshaler\r
- *\r
- * Copyright 2002,2005 Marcus Meissner\r
- *\r
- * The olerelay debug channel allows you to see calls marshalled by\r
- * the typelib marshaller. It is not a generic COM relaying system.\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- */\r
-\r
-#include "config.h"\r
-\r
-#include <assert.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include <ctype.h>\r
-\r
-#define COBJMACROS\r
-#define NONAMELESSUNION\r
-#define NONAMELESSSTRUCT\r
-\r
-#include "winerror.h"\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "winnls.h"\r
-#include "winreg.h"\r
-#include "winuser.h"\r
-\r
-#include "ole2.h"\r
-#include "typelib.h"\r
-#include "wine/debug.h"\r
-\r
-static const WCHAR riidW[5] = {'r','i','i','d',0};\r
-static const WCHAR pdispparamsW[] = {'p','d','i','s','p','p','a','r','a','m','s',0};\r
-static const WCHAR ppvObjectW[] = {'p','p','v','O','b','j','e','c','t',0};\r
-static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0};\r
-static const WCHAR GetIDsOfNamesW[] = { 'G','e','t','I','D','s','O','f','N','a','m','e','s',0};\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
-WINE_DECLARE_DEBUG_CHANNEL(olerelay);\r
-\r
-#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))\r
-\r
-typedef struct _marshal_state {\r
- LPBYTE base;\r
- int size;\r
- int curoff;\r
-\r
- BOOL thisisiid;\r
- IID iid; /* HACK: for VT_VOID */\r
-} marshal_state;\r
-\r
-/* used in the olerelay code to avoid having the L"" stuff added by debugstr_w */\r
-static char *relaystr(WCHAR *in) {\r
- char *tmp = (char *)debugstr_w(in);\r
- tmp += 2;\r
- tmp[strlen(tmp)-1] = '\0';\r
- return tmp;\r
-}\r
-\r
-static HRESULT\r
-xbuf_add(marshal_state *buf, LPBYTE stuff, DWORD size) {\r
- while (buf->size - buf->curoff < size) {\r
- if (buf->base) {\r
- buf->size += 100;\r
- buf->base = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,buf->base,buf->size);\r
- if (!buf->base)\r
- return E_OUTOFMEMORY;\r
- } else {\r
- buf->base = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,32);\r
- buf->size = 32;\r
- if (!buf->base)\r
- return E_OUTOFMEMORY;\r
- }\r
- }\r
- memcpy(buf->base+buf->curoff,stuff,size);\r
- buf->curoff += size;\r
- return S_OK;\r
-}\r
-\r
-static HRESULT\r
-xbuf_get(marshal_state *buf, LPBYTE stuff, DWORD size) {\r
- if (buf->size < buf->curoff+size) return E_FAIL;\r
- memcpy(stuff,buf->base+buf->curoff,size);\r
- buf->curoff += size;\r
- return S_OK;\r
-}\r
-\r
-static HRESULT\r
-xbuf_skip(marshal_state *buf, DWORD size) {\r
- if (buf->size < buf->curoff+size) return E_FAIL;\r
- buf->curoff += size;\r
- return S_OK;\r
-}\r
-\r
-static HRESULT\r
-_unmarshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN *pUnk) {\r
- IStream *pStm;\r
- ULARGE_INTEGER newpos;\r
- LARGE_INTEGER seekto;\r
- ULONG res;\r
- HRESULT hres;\r
- DWORD xsize;\r
-\r
- TRACE("...%s...\n",debugstr_guid(riid));\r
- \r
- *pUnk = NULL;\r
- hres = xbuf_get(buf,(LPBYTE)&xsize,sizeof(xsize));\r
- if (hres) {\r
- ERR("xbuf_get failed\n");\r
- return hres;\r
- }\r
- \r
- if (xsize == 0) return S_OK;\r
- \r
- hres = CreateStreamOnHGlobal(0,TRUE,&pStm);\r
- if (hres) {\r
- ERR("Stream create failed %lx\n",hres);\r
- return hres;\r
- }\r
- \r
- hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res);\r
- if (hres) {\r
- ERR("stream write %lx\n",hres);\r
- return hres;\r
- }\r
- \r
- memset(&seekto,0,sizeof(seekto));\r
- hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);\r
- if (hres) {\r
- ERR("Failed Seek %lx\n",hres);\r
- return hres;\r
- }\r
- \r
- hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk);\r
- if (hres) {\r
- ERR("Unmarshalling interface %s failed with %lx\n",debugstr_guid(riid),hres);\r
- return hres;\r
- }\r
- \r
- IStream_Release(pStm);\r
- return xbuf_skip(buf,xsize);\r
-}\r
-\r
-static HRESULT\r
-_marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) {\r
- LPUNKNOWN newiface = NULL;\r
- LPBYTE tempbuf = NULL;\r
- IStream *pStm = NULL;\r
- STATSTG ststg;\r
- ULARGE_INTEGER newpos;\r
- LARGE_INTEGER seekto;\r
- ULONG res;\r
- DWORD xsize;\r
- HRESULT hres;\r
-\r
- if (!pUnk) {\r
- /* this is valid, if for instance we serialize\r
- * a VT_DISPATCH with NULL ptr which apparently\r
- * can happen. S_OK to make sure we continue\r
- * serializing.\r
- */\r
- ERR("pUnk is NULL?\n");\r
- xsize = 0;\r
- return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));\r
- }\r
-\r
- hres = E_FAIL;\r
-\r
- TRACE("...%s...\n",debugstr_guid(riid));\r
- hres = IUnknown_QueryInterface(pUnk,riid,(LPVOID*)&newiface);\r
- if (hres) {\r
- WARN("%p does not support iface %s\n",pUnk,debugstr_guid(riid));\r
- goto fail;\r
- }\r
- \r
- hres = CreateStreamOnHGlobal(0,TRUE,&pStm);\r
- if (hres) {\r
- ERR("Stream create failed %lx\n",hres);\r
- goto fail;\r
- }\r
- \r
- hres = CoMarshalInterface(pStm,riid,newiface,0,NULL,0);\r
- if (hres) {\r
- ERR("Marshalling interface %s failed with %lx\n", debugstr_guid(riid), hres);\r
- goto fail;\r
- }\r
- \r
- hres = IStream_Stat(pStm,&ststg,0);\r
- if (hres) {\r
- ERR("Stream stat failed\n");\r
- goto fail;\r
- }\r
- \r
- tempbuf = HeapAlloc(GetProcessHeap(), 0, ststg.cbSize.u.LowPart);\r
- memset(&seekto,0,sizeof(seekto));\r
- hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);\r
- if (hres) {\r
- ERR("Failed Seek %lx\n",hres);\r
- goto fail;\r
- }\r
- \r
- hres = IStream_Read(pStm,tempbuf,ststg.cbSize.u.LowPart,&res);\r
- if (hres) {\r
- ERR("Failed Read %lx\n",hres);\r
- goto fail;\r
- }\r
- \r
- xsize = ststg.cbSize.u.LowPart;\r
- xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));\r
- hres = xbuf_add(buf,tempbuf,ststg.cbSize.u.LowPart);\r
- \r
- HeapFree(GetProcessHeap(),0,tempbuf);\r
- IUnknown_Release(newiface);\r
- IStream_Release(pStm);\r
- \r
- return hres;\r
- \r
-fail:\r
- xsize = 0;\r
- xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));\r
- if (pStm) IUnknown_Release(pStm);\r
- if (newiface) IUnknown_Release(newiface);\r
- HeapFree(GetProcessHeap(), 0, tempbuf);\r
- return hres;\r
-}\r
-\r
-/********************* OLE Proxy/Stub Factory ********************************/\r
-static HRESULT WINAPI\r
-PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) {\r
- if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) {\r
- *ppv = (LPVOID)iface;\r
- /* No ref counting, static class */\r
- return S_OK;\r
- }\r
- FIXME("(%s) unknown IID?\n",debugstr_guid(iid));\r
- return E_NOINTERFACE;\r
-}\r
-\r
-static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; }\r
-static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; }\r
-\r
-static HRESULT\r
-_get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {\r
- HRESULT hres;\r
- HKEY ikey;\r
- char tlguid[200],typelibkey[300],interfacekey[300],ver[100];\r
- char tlfn[260];\r
- OLECHAR tlfnW[260];\r
- DWORD tlguidlen, verlen, type, tlfnlen;\r
- ITypeLib *tl;\r
-\r
- sprintf( interfacekey, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",\r
- riid->Data1, riid->Data2, riid->Data3,\r
- riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],\r
- riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]\r
- );\r
-\r
- if (RegOpenKeyA(HKEY_CLASSES_ROOT,interfacekey,&ikey)) {\r
- ERR("No %s key found.\n",interfacekey);\r
- return E_FAIL;\r
- }\r
- type = (1<<REG_SZ);\r
- tlguidlen = sizeof(tlguid);\r
- if (RegQueryValueExA(ikey,NULL,NULL,&type,tlguid,&tlguidlen)) {\r
- ERR("Getting typelib guid failed.\n");\r
- RegCloseKey(ikey);\r
- return E_FAIL;\r
- }\r
- type = (1<<REG_SZ);\r
- verlen = sizeof(ver);\r
- if (RegQueryValueExA(ikey,"Version",NULL,&type,ver,&verlen)) {\r
- ERR("Could not get version value?\n");\r
- RegCloseKey(ikey);\r
- return E_FAIL;\r
- }\r
- RegCloseKey(ikey);\r
- sprintf(typelibkey,"Typelib\\%s\\%s\\0\\win32",tlguid,ver);\r
- tlfnlen = sizeof(tlfn);\r
- if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) {\r
- ERR("Could not get typelib fn?\n");\r
- return E_FAIL;\r
- }\r
- MultiByteToWideChar(CP_ACP, 0, tlfn, -1, tlfnW, -1);\r
- hres = LoadTypeLib(tlfnW,&tl);\r
- if (hres) {\r
- ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid));\r
- return hres;\r
- }\r
- hres = ITypeLib_GetTypeInfoOfGuid(tl,riid,ti);\r
- if (hres) {\r
- ERR("typelib does not contain info for %s?\n",debugstr_guid(riid));\r
- ITypeLib_Release(tl);\r
- return hres;\r
- }\r
- /* FIXME: do this? ITypeLib_Release(tl); */\r
- return hres;\r
-}\r
-\r
-/* Determine nr of functions. Since we use the toplevel interface and all\r
- * inherited ones have lower numbers, we are ok to not to descent into\r
- * the inheritance tree I think.\r
- */\r
-static int _nroffuncs(ITypeInfo *tinfo) {\r
- int n, max = 0;\r
- FUNCDESC *fdesc;\r
- HRESULT hres;\r
-\r
- n=0;\r
- while (1) {\r
- hres = ITypeInfo_GetFuncDesc(tinfo,n,&fdesc);\r
- if (hres)\r
- return max+1;\r
- if (fdesc->oVft/4 > max)\r
- max = fdesc->oVft/4;\r
- n++;\r
- }\r
- /*NOTREACHED*/\r
-}\r
-\r
-#ifdef __i386__\r
-\r
-#include "pshpack1.h"\r
-\r
-typedef struct _TMAsmProxy {\r
- BYTE popleax;\r
- BYTE pushlval;\r
- BYTE nr;\r
- BYTE pushleax;\r
- BYTE lcall;\r
- DWORD xcall;\r
- BYTE lret;\r
- WORD bytestopop;\r
-} TMAsmProxy;\r
-\r
-#include "poppack.h"\r
-\r
-#else /* __i386__ */\r
-# error You need to implement stubless proxies for your architecture\r
-#endif\r
-\r
-typedef struct _TMProxyImpl {\r
- LPVOID *lpvtbl;\r
- IRpcProxyBufferVtbl *lpvtbl2;\r
- ULONG ref;\r
-\r
- TMAsmProxy *asmstubs;\r
- ITypeInfo* tinfo;\r
- IRpcChannelBuffer* chanbuf;\r
- IID iid;\r
- CRITICAL_SECTION crit;\r
- IUnknown *outerunknown;\r
-} TMProxyImpl;\r
-\r
-static HRESULT WINAPI\r
-TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv)\r
-{\r
- TRACE("()\n");\r
- if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) {\r
- *ppv = (LPVOID)iface;\r
- IRpcProxyBuffer_AddRef(iface);\r
- return S_OK;\r
- }\r
- FIXME("no interface for %s\n",debugstr_guid(riid));\r
- return E_NOINTERFACE;\r
-}\r
-\r
-static ULONG WINAPI\r
-TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface)\r
-{\r
- ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);\r
- ULONG refCount = InterlockedIncrement(&This->ref);\r
-\r
- TRACE("(%p)->(ref before=%lu)\n",This, refCount - 1);\r
-\r
- return refCount;\r
-}\r
-\r
-static ULONG WINAPI\r
-TMProxyImpl_Release(LPRPCPROXYBUFFER iface)\r
-{\r
- ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);\r
- ULONG refCount = InterlockedDecrement(&This->ref);\r
-\r
- TRACE("(%p)->(ref before=%lu)\n",This, refCount + 1);\r
-\r
- if (!refCount)\r
- {\r
- DeleteCriticalSection(&This->crit);\r
- if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf);\r
- VirtualFree(This->asmstubs, 0, MEM_RELEASE);\r
- CoTaskMemFree(This);\r
- }\r
- return refCount;\r
-}\r
-\r
-static HRESULT WINAPI\r
-TMProxyImpl_Connect(\r
- LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer)\r
-{\r
- ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);\r
-\r
- TRACE("(%p)\n", pRpcChannelBuffer);\r
-\r
- EnterCriticalSection(&This->crit);\r
-\r
- IRpcChannelBuffer_AddRef(pRpcChannelBuffer);\r
- This->chanbuf = pRpcChannelBuffer;\r
-\r
- LeaveCriticalSection(&This->crit);\r
-\r
- return S_OK;\r
-}\r
-\r
-static void WINAPI\r
-TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface)\r
-{\r
- ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);\r
-\r
- TRACE("()\n");\r
-\r
- EnterCriticalSection(&This->crit);\r
-\r
- IRpcChannelBuffer_Release(This->chanbuf);\r
- This->chanbuf = NULL;\r
-\r
- LeaveCriticalSection(&This->crit);\r
-}\r
-\r
-\r
-static IRpcProxyBufferVtbl tmproxyvtable = {\r
- TMProxyImpl_QueryInterface,\r
- TMProxyImpl_AddRef,\r
- TMProxyImpl_Release,\r
- TMProxyImpl_Connect,\r
- TMProxyImpl_Disconnect\r
-};\r
-\r
-/* how much space do we use on stack in DWORD steps. */\r
-int\r
-_argsize(DWORD vt) {\r
- switch (vt) {\r
- case VT_DATE:\r
- return sizeof(DATE)/sizeof(DWORD);\r
- case VT_VARIANT:\r
- return (sizeof(VARIANT)+3)/sizeof(DWORD);\r
- default:\r
- return 1;\r
- }\r
-}\r
-\r
-static int\r
-_xsize(TYPEDESC *td) {\r
- switch (td->vt) {\r
- case VT_DATE:\r
- return sizeof(DATE);\r
- case VT_VARIANT:\r
- return sizeof(VARIANT)+3;\r
- case VT_CARRAY: {\r
- int i, arrsize = 1;\r
- ARRAYDESC *adesc = td->u.lpadesc;\r
-\r
- for (i=0;i<adesc->cDims;i++)\r
- arrsize *= adesc->rgbounds[i].cElements;\r
- return arrsize*_xsize(&adesc->tdescElem);\r
- }\r
- case VT_UI2:\r
- case VT_I2:\r
- return 2;\r
- case VT_UI1:\r
- case VT_I1:\r
- return 1;\r
- default:\r
- return 4;\r
- }\r
-}\r
-\r
-static HRESULT\r
-serialize_param(\r
- ITypeInfo *tinfo,\r
- BOOL writeit,\r
- BOOL debugout,\r
- BOOL dealloc,\r
- TYPEDESC *tdesc,\r
- DWORD *arg,\r
- marshal_state *buf)\r
-{\r
- HRESULT hres = S_OK;\r
-\r
- TRACE("(tdesc.vt %d)\n",tdesc->vt);\r
-\r
- switch (tdesc->vt) {\r
- case VT_EMPTY: /* nothing. empty variant for instance */\r
- return S_OK;\r
- case VT_BOOL:\r
- case VT_ERROR:\r
- case VT_UINT:\r
- case VT_I4:\r
- case VT_R4:\r
- case VT_UI4:\r
- hres = S_OK;\r
- if (debugout) TRACE_(olerelay)("%lx",*arg);\r
- if (writeit)\r
- hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));\r
- return hres;\r
- case VT_I2:\r
- case VT_UI2:\r
- hres = S_OK;\r
- if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);\r
- if (writeit)\r
- hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));\r
- return hres;\r
- case VT_I1:\r
- case VT_UI1:\r
- hres = S_OK;\r
- if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);\r
- if (writeit)\r
- hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));\r
- return hres;\r
- case VT_I4|VT_BYREF:\r
- hres = S_OK;\r
- if (debugout) TRACE_(olerelay)("&0x%lx",*arg);\r
- if (writeit)\r
- hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD));\r
- /* do not dealloc at this time */\r
- return hres;\r
- case VT_VARIANT: {\r
- TYPEDESC tdesc2;\r
- VARIANT *vt = (VARIANT*)arg;\r
- DWORD vttype = V_VT(vt);\r
-\r
- if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype);\r
- tdesc2.vt = vttype;\r
- if (writeit) {\r
- hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));\r
- if (hres) return hres;\r
- }\r
- /* need to recurse since we need to free the stuff */\r
- hres = serialize_param(tinfo,writeit,debugout,dealloc,&tdesc2,&(V_I4(vt)),buf);\r
- if (debugout) TRACE_(olerelay)(")");\r
- return hres;\r
- }\r
- case VT_BSTR|VT_BYREF: {\r
- if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>");\r
- if (writeit) {\r
- /* ptr to ptr to magic widestring, basically */\r
- BSTR *bstr = (BSTR *) *arg;\r
- if (!*bstr) {\r
- /* -1 means "null string" which is equivalent to empty string */\r
- DWORD fakelen = -1; \r
- xbuf_add(buf, (LPBYTE)&fakelen,4);\r
- } else {\r
- /* BSTRs store the length behind the first character */\r
- DWORD *len = ((DWORD *)(*bstr))-1;\r
- hres = xbuf_add(buf, (LPBYTE) len, *len + 4);\r
- if (hres) return hres;\r
- }\r
- }\r
-\r
- if (dealloc && arg) {\r
- BSTR *str = *((BSTR **)arg);\r
- SysFreeString(*str);\r
- }\r
- return S_OK;\r
- }\r
- \r
- case VT_BSTR: {\r
- if (debugout) {\r
- if (*arg)\r
- TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg));\r
- else\r
- TRACE_(olerelay)("<bstr NULL>");\r
- }\r
- if (writeit) {\r
- if (!*arg) {\r
- DWORD fakelen = -1;\r
- hres = xbuf_add(buf,(LPBYTE)&fakelen,4);\r
- if (hres)\r
- return hres;\r
- } else {\r
- DWORD *bstr = ((DWORD*)(*arg))-1;\r
-\r
- hres = xbuf_add(buf,(LPBYTE)bstr,bstr[0]+4);\r
- if (hres)\r
- return hres;\r
- }\r
- }\r
-\r
- if (dealloc && arg)\r
- SysFreeString((BSTR)*arg);\r
- return S_OK;\r
- }\r
- case VT_PTR: {\r
- DWORD cookie;\r
-\r
- if (debugout) TRACE_(olerelay)("*");\r
- /* Write always, so the other side knows when it gets a NULL pointer.\r
- */\r
- cookie = *arg ? 0x42424242 : 0;\r
- hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));\r
- if (hres)\r
- return hres;\r
- if (!*arg) {\r
- if (debugout) TRACE_(olerelay)("NULL");\r
- return S_OK;\r
- }\r
- hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf);\r
- if (dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)arg);\r
- return hres;\r
- }\r
- case VT_UNKNOWN:\r
- if (debugout) TRACE_(olerelay)("unk(0x%lx)",*arg);\r
- if (writeit)\r
- hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg);\r
- return hres;\r
- case VT_DISPATCH:\r
- if (debugout) TRACE_(olerelay)("idisp(0x%lx)",*arg);\r
- if (writeit)\r
- hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg);\r
- return hres;\r
- case VT_VOID:\r
- if (debugout) TRACE_(olerelay)("<void>");\r
- return S_OK;\r
- case VT_USERDEFINED: {\r
- ITypeInfo *tinfo2;\r
- TYPEATTR *tattr;\r
-\r
- hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);\r
- if (hres) {\r
- ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);\r
- return hres;\r
- }\r
- ITypeInfo_GetTypeAttr(tinfo2,&tattr);\r
- switch (tattr->typekind) {\r
- case TKIND_DISPATCH:\r
- case TKIND_INTERFACE:\r
- if (writeit)\r
- hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg);\r
- break;\r
- case TKIND_RECORD: {\r
- int i;\r
- if (debugout) TRACE_(olerelay)("{");\r
- for (i=0;i<tattr->cVars;i++) {\r
- VARDESC *vdesc;\r
- ELEMDESC *elem2;\r
- TYPEDESC *tdesc2;\r
-\r
- hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);\r
- if (hres) {\r
- ERR("Could not get vardesc of %d\n",i);\r
- return hres;\r
- }\r
- /* Need them for hack below */\r
- /*\r
- memset(names,0,sizeof(names));\r
- hres = ITypeInfo_GetNames(tinfo2,vdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);\r
- if (nrofnames > sizeof(names)/sizeof(names[0])) {\r
- ERR("Need more names!\n");\r
- }\r
- if (!hres && debugout)\r
- TRACE_(olerelay)("%s=",relaystr(names[0]));\r
- */\r
- elem2 = &vdesc->elemdescVar;\r
- tdesc2 = &elem2->tdesc;\r
- hres = serialize_param(\r
- tinfo2,\r
- writeit,\r
- debugout,\r
- dealloc,\r
- tdesc2,\r
- (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst),\r
- buf\r
- );\r
- if (hres!=S_OK)\r
- return hres;\r
- if (debugout && (i<(tattr->cVars-1)))\r
- TRACE_(olerelay)(",");\r
- }\r
- if (buf->thisisiid && (tattr->cbSizeInstance==sizeof(GUID)))\r
- memcpy(&(buf->iid),arg,sizeof(buf->iid));\r
- if (debugout) TRACE_(olerelay)("}");\r
- break;\r
- }\r
- default:\r
- FIXME("Unhandled typekind %d\n",tattr->typekind);\r
- hres = E_FAIL;\r
- break;\r
- }\r
- ITypeInfo_Release(tinfo2);\r
- return hres;\r
- }\r
- case VT_CARRAY: {\r
- ARRAYDESC *adesc = tdesc->u.lpadesc;\r
- int i, arrsize = 1;\r
-\r
- if (debugout) TRACE_(olerelay)("carr");\r
- for (i=0;i<adesc->cDims;i++) {\r
- if (debugout) TRACE_(olerelay)("[%ld]",adesc->rgbounds[i].cElements);\r
- arrsize *= adesc->rgbounds[i].cElements;\r
- }\r
- if (debugout) TRACE_(olerelay)("(vt %d)",adesc->tdescElem.vt);\r
- if (debugout) TRACE_(olerelay)("[");\r
- for (i=0;i<arrsize;i++) {\r
- hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);\r
- if (hres)\r
- return hres;\r
- if (debugout && (i<arrsize-1)) TRACE_(olerelay)(",");\r
- }\r
- if (debugout) TRACE_(olerelay)("]");\r
- return S_OK;\r
- }\r
- default:\r
- ERR("Unhandled marshal type %d.\n",tdesc->vt);\r
- return S_OK;\r
- }\r
-}\r
-\r
-/* IDL desc:\r
- * HRESULT GetIDsOfNames(\r
- * [in] REFIID riid, args[1]\r
- * [in, size_is(cNames)] LPOLESTR *rgszNames, args[2]\r
- * [in] UINT cNames, args[3]\r
- * [in] LCID lcid, args[4]\r
- * [out, size_is(cNames)] DISPID *rgDispId); args[5]\r
- *\r
- * line format:\r
- * IID iid;\r
- * DWORD cNames;\r
- * LPOLESTR rgszNames[cNames];\r
- * DWORD bytestrlen (incl 0)\r
- * BYTE data[bytestrlen] (incl 0)\r
- * LCID\r
- */\r
-static HRESULT\r
-serialize_IDispatch_GetIDsOfNames(\r
- BOOL inputparams,\r
- BOOL debugout,\r
- DWORD *args,\r
- marshal_state *buf)\r
-{\r
- HRESULT hres;\r
- DWORD cNames = args[2];\r
- LPOLESTR *rgszNames = (LPOLESTR*)args[1];\r
- int i;\r
-\r
- if (inputparams) {\r
- if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0]));\r
- hres = xbuf_add(buf, (LPBYTE)args[0], sizeof(IID));\r
- if (hres) {\r
- FIXME("serialize of IID failed.\n");\r
- return hres;\r
- }\r
- if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames);\r
- hres = xbuf_add(buf, (LPBYTE)&cNames, sizeof(DWORD));\r
- if (hres) {\r
- FIXME("serialize of cNames failed.\n");\r
- return hres;\r
- }\r
- if (debugout) TRACE_(olerelay)("rgszNames=[");\r
- for (i=0;i<cNames;i++) {\r
- DWORD len = 2*(lstrlenW(rgszNames[i])+1);\r
-\r
- if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));\r
- hres = xbuf_add(buf, (LPBYTE)&len, sizeof(DWORD));\r
- if (hres) {\r
- FIXME("serialize of len failed.\n");\r
- return hres;\r
- }\r
- hres = xbuf_add(buf, (LPBYTE)rgszNames[i], len);\r
- if (hres) {\r
- FIXME("serialize of rgszNames[i] failed.\n");\r
- return hres;\r
- }\r
- }\r
- if (debugout) TRACE_(olerelay)("],lcid=%04lx)",args[3]);\r
- hres = xbuf_add(buf, (LPBYTE)&args[3], sizeof(DWORD));\r
- if (hres) {\r
- FIXME("serialize of lcid failed.\n");\r
- return hres;\r
- }\r
- } else {\r
- DISPID *rgDispId = (DISPID*)args[4];\r
-\r
- hres = xbuf_add(buf, (LPBYTE)rgDispId, sizeof(DISPID) * cNames);\r
- if (hres) {\r
- FIXME("serialize of rgDispId failed.\n");\r
- return hres;\r
- }\r
- if (debugout) {\r
- TRACE_(olerelay)("riid=[in],rgszNames=[in],cNames=[in],rgDispId=[");\r
- for (i=0;i<cNames;i++)\r
- TRACE_(olerelay)("%08lx,",rgDispId[i]);\r
- TRACE_(olerelay)("])");\r
- }\r
- HeapFree(GetProcessHeap(),0,(IID*)args[0]);\r
- rgszNames = (LPOLESTR*)args[1];\r
- for (i=0;i<cNames;i++) HeapFree(GetProcessHeap(),0,rgszNames[i]);\r
- HeapFree(GetProcessHeap(),0,rgszNames);\r
- HeapFree(GetProcessHeap(),0,rgDispId);\r
- }\r
- return S_OK;\r
-}\r
-\r
-static HRESULT\r
-deserialize_IDispatch_GetIDsOfNames(\r
- BOOL inputparams,\r
- BOOL debugout,\r
- DWORD *args,\r
- marshal_state *buf)\r
-{\r
- HRESULT hres;\r
- DWORD cNames;\r
- LPOLESTR *rgszNames;\r
- int i;\r
-\r
- if (inputparams) {\r
- args[0] = (DWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IID));\r
- if (!args[0]) return E_FAIL;\r
- hres = xbuf_get(buf, (LPBYTE)args[0], sizeof(IID));\r
- if (hres) {\r
- FIXME("deserialize of IID failed.\n");\r
- return hres;\r
- }\r
- if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0]));\r
-\r
- hres = xbuf_get(buf, (LPBYTE)&cNames, sizeof(DWORD));\r
- if (hres) {\r
- FIXME("deserialize of cNames failed.\n");\r
- return hres;\r
- }\r
- args[2] = cNames;\r
- if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames);\r
- if (debugout) TRACE_(olerelay)("rgszNames=[");\r
- rgszNames = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPOLESTR) * cNames);\r
- if (!rgszNames) return E_FAIL;\r
- args[1] = (DWORD)rgszNames;\r
- for (i=0;i<cNames;i++) {\r
- DWORD len;\r
-\r
- hres = xbuf_get(buf, (LPBYTE)&len, sizeof(DWORD));\r
- if (hres) {\r
- FIXME("serialize of len failed.\n");\r
- return hres;\r
- }\r
- rgszNames[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);\r
- if (!rgszNames[i]) {\r
- FIXME("heapalloc of %ld bytes failed\n", len);\r
- return E_FAIL;\r
- }\r
- hres = xbuf_get(buf, (LPBYTE)rgszNames[i], len);\r
- if (hres) {\r
- FIXME("serialize of rgszNames[i] failed.\n");\r
- return hres;\r
- }\r
- if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));\r
- }\r
- hres = xbuf_get(buf, (LPBYTE)&args[3], sizeof(DWORD));\r
- if (hres) {\r
- FIXME("deserialize of lcid failed.\n");\r
- return hres;\r
- }\r
- if (debugout) TRACE_(olerelay)("],lcid=%04lx,rgDispId=[out])",args[3]);\r
- args[4] = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPID) * cNames);\r
- } else {\r
- hres = xbuf_get(buf, (LPBYTE)args[4], sizeof(DISPID) * args[2]);\r
- if (hres) {\r
- FIXME("serialize of rgDispId failed.\n");\r
- return hres;\r
- }\r
- if (debugout) {\r
- TRACE_(olerelay)("dispid=[");\r
- for (i=0;i<args[2];i++)\r
- TRACE_(olerelay)("%08lx,",((DISPID*)args[4])[i]);\r
- TRACE_(olerelay)("])");\r
- }\r
- }\r
- return S_OK;\r
-}\r
-\r
-static HRESULT\r
-serialize_LPVOID_ptr(\r
- ITypeInfo *tinfo,\r
- BOOL writeit,\r
- BOOL debugout,\r
- BOOL dealloc,\r
- TYPEDESC *tdesc,\r
- DWORD *arg,\r
- marshal_state *buf)\r
-{\r
- HRESULT hres;\r
- DWORD cookie;\r
-\r
- if ((tdesc->vt != VT_PTR) ||\r
- (tdesc->u.lptdesc->vt != VT_PTR) ||\r
- (tdesc->u.lptdesc->u.lptdesc->vt != VT_VOID)\r
- ) {\r
- FIXME("ppvObject not expressed as VT_PTR -> VT_PTR -> VT_VOID?\n");\r
- return E_FAIL;\r
- }\r
- cookie = (*(DWORD*)*arg) ? 0x42424242: 0x0;\r
- if (writeit) {\r
- hres = xbuf_add(buf, (LPVOID)&cookie, sizeof(cookie));\r
- if (hres)\r
- return hres;\r
- }\r
- if (!*(DWORD*)*arg) {\r
- if (debugout) TRACE_(olerelay)("<lpvoid NULL>");\r
- return S_OK;\r
- }\r
- if (debugout)\r
- TRACE_(olerelay)("ppv(%p)",*(LPUNKNOWN*)*arg);\r
- if (writeit) {\r
- hres = _marshal_interface(buf,&(buf->iid),*(LPUNKNOWN*)*arg);\r
- if (hres)\r
- return hres;\r
- }\r
- if (dealloc)\r
- HeapFree(GetProcessHeap(),0,(LPVOID)*arg);\r
- return S_OK;\r
-}\r
-\r
-static HRESULT\r
-serialize_DISPPARAM_ptr(\r
- ITypeInfo *tinfo,\r
- BOOL writeit,\r
- BOOL debugout,\r
- BOOL dealloc,\r
- TYPEDESC *tdesc,\r
- DWORD *arg,\r
- marshal_state *buf)\r
-{\r
- DWORD cookie;\r
- HRESULT hres;\r
- DISPPARAMS *disp;\r
- int i;\r
-\r
- if ((tdesc->vt != VT_PTR) || (tdesc->u.lptdesc->vt != VT_USERDEFINED)) {\r
- FIXME("DISPPARAMS not expressed as VT_PTR -> VT_USERDEFINED?\n");\r
- return E_FAIL;\r
- }\r
-\r
- cookie = *arg ? 0x42424242 : 0x0;\r
- if (writeit) {\r
- hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));\r
- if (hres)\r
- return hres;\r
- }\r
- if (!*arg) {\r
- if (debugout) TRACE_(olerelay)("<DISPPARAMS NULL>");\r
- return S_OK;\r
- }\r
- disp = (DISPPARAMS*)*arg;\r
- if (writeit) {\r
- hres = xbuf_add(buf,(LPBYTE)&disp->cArgs,sizeof(disp->cArgs));\r
- if (hres)\r
- return hres;\r
- }\r
- if (debugout) TRACE_(olerelay)("D{");\r
- for (i=0;i<disp->cArgs;i++) {\r
- TYPEDESC vtdesc;\r
-\r
- vtdesc.vt = VT_VARIANT;\r
- serialize_param(\r
- tinfo,\r
- writeit,\r
- debugout,\r
- dealloc,\r
- &vtdesc,\r
- (DWORD*)(disp->rgvarg+i),\r
- buf\r
- );\r
- if (debugout && (i<disp->cArgs-1))\r
- TRACE_(olerelay)(",");\r
- }\r
- if (dealloc)\r
- HeapFree(GetProcessHeap(),0,disp->rgvarg);\r
- if (writeit) {\r
- hres = xbuf_add(buf,(LPBYTE)&disp->cNamedArgs,sizeof(disp->cNamedArgs));\r
- if (hres)\r
- return hres;\r
- }\r
- if (debugout) TRACE_(olerelay)("}{");\r
- for (i=0;i<disp->cNamedArgs;i++) {\r
- TYPEDESC vtdesc;\r
-\r
- vtdesc.vt = VT_UINT;\r
- serialize_param(\r
- tinfo,\r
- writeit,\r
- debugout,\r
- dealloc,\r
- &vtdesc,\r
- (DWORD*)(disp->rgdispidNamedArgs+i),\r
- buf\r
- );\r
- if (debugout && (i<disp->cNamedArgs-1))\r
- TRACE_(olerelay)(",");\r
- }\r
- if (debugout) TRACE_(olerelay)("}");\r
- if (dealloc) {\r
- HeapFree(GetProcessHeap(),0,disp->rgdispidNamedArgs);\r
- HeapFree(GetProcessHeap(),0,disp);\r
- }\r
- return S_OK;\r
-}\r
-\r
-static HRESULT\r
-deserialize_param(\r
- ITypeInfo *tinfo,\r
- BOOL readit,\r
- BOOL debugout,\r
- BOOL alloc,\r
- TYPEDESC *tdesc,\r
- DWORD *arg,\r
- marshal_state *buf)\r
-{\r
- HRESULT hres = S_OK;\r
-\r
- TRACE("vt %d at %p\n",tdesc->vt,arg);\r
-\r
- while (1) {\r
- switch (tdesc->vt) {\r
- case VT_EMPTY:\r
- if (debugout) TRACE_(olerelay)("<empty>");\r
- return S_OK;\r
- case VT_NULL:\r
- if (debugout) TRACE_(olerelay)("<null>");\r
- return S_OK;\r
- case VT_VARIANT: {\r
- VARIANT *vt = (VARIANT*)arg;\r
-\r
- if (readit) {\r
- DWORD vttype;\r
- TYPEDESC tdesc2;\r
- hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype));\r
- if (hres) {\r
- FIXME("vt type not read?\n");\r
- return hres;\r
- }\r
- memset(&tdesc2,0,sizeof(tdesc2));\r
- tdesc2.vt = vttype;\r
- V_VT(vt) = vttype;\r
- if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype);\r
- hres = deserialize_param(tinfo, readit, debugout, alloc, &tdesc2, &(V_I4(vt)), buf);\r
- TRACE_(olerelay)(")");\r
- return hres;\r
- } else {\r
- VariantInit(vt);\r
- return S_OK;\r
- }\r
- }\r
- case VT_ERROR:\r
- case VT_BOOL:\r
- case VT_I4:\r
- case VT_UINT:\r
- case VT_R4:\r
- case VT_UI4:\r
- if (readit) {\r
- hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));\r
- if (hres) ERR("Failed to read integer 4 byte\n");\r
- }\r
- if (debugout) TRACE_(olerelay)("%lx",*arg);\r
- return hres;\r
- case VT_I2:\r
- case VT_UI2:\r
- if (readit) {\r
- DWORD x;\r
- hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));\r
- if (hres) ERR("Failed to read integer 4 byte\n");\r
- memcpy(arg,&x,2);\r
- }\r
- if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);\r
- return hres;\r
- case VT_I1:\r
- case VT_UI1:\r
- if (readit) {\r
- DWORD x;\r
- hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));\r
- if (hres) ERR("Failed to read integer 4 byte\n");\r
- memcpy(arg,&x,1);\r
- }\r
- if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);\r
- return hres;\r
- case VT_I4|VT_BYREF:\r
- hres = S_OK;\r
- if (alloc)\r
- *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));\r
- if (readit) {\r
- hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD));\r
- if (hres) ERR("Failed to read integer 4 byte\n");\r
- }\r
- if (debugout) TRACE_(olerelay)("&0x%lx",*(DWORD*)*arg);\r
- return hres;\r
- case VT_BSTR|VT_BYREF: {\r
- BSTR **bstr = (BSTR **)arg;\r
- WCHAR *str;\r
- DWORD len;\r
-\r
- if (readit) {\r
- hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));\r
- if (hres) {\r
- ERR("failed to read bstr klen\n");\r
- return hres;\r
- }\r
- if (len == -1) {\r
- *bstr = CoTaskMemAlloc(sizeof(BSTR *));\r
- **bstr = NULL;\r
- if (debugout) TRACE_(olerelay)("<bstr NULL>");\r
- } else {\r
- str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR));\r
- hres = xbuf_get(buf,(LPBYTE)str,len);\r
- if (hres) {\r
- ERR("Failed to read BSTR.\n");\r
- return hres;\r
- }\r
- *bstr = CoTaskMemAlloc(sizeof(BSTR *));\r
- **bstr = SysAllocStringLen(str,len);\r
- if (debugout) TRACE_(olerelay)("%s",relaystr(str));\r
- HeapFree(GetProcessHeap(),0,str);\r
- }\r
- } else {\r
- *bstr = NULL;\r
- }\r
- return S_OK;\r
- }\r
- case VT_BSTR: {\r
- WCHAR *str;\r
- DWORD len;\r
-\r
- if (readit) {\r
- hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));\r
- if (hres) {\r
- ERR("failed to read bstr klen\n");\r
- return hres;\r
- }\r
- if (len == -1) {\r
- *arg = 0;\r
- if (debugout) TRACE_(olerelay)("<bstr NULL>");\r
- } else {\r
- str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR));\r
- hres = xbuf_get(buf,(LPBYTE)str,len);\r
- if (hres) {\r
- ERR("Failed to read BSTR.\n");\r
- return hres;\r
- }\r
- *arg = (DWORD)SysAllocStringLen(str,len);\r
- if (debugout) TRACE_(olerelay)("%s",relaystr(str));\r
- HeapFree(GetProcessHeap(),0,str);\r
- }\r
- } else {\r
- *arg = 0;\r
- }\r
- return S_OK;\r
- }\r
- case VT_PTR: {\r
- DWORD cookie;\r
- BOOL derefhere = 0;\r
-\r
- derefhere = (tdesc->u.lptdesc->vt != VT_USERDEFINED);\r
- /* read it in all cases, we need to know if we have \r
- * NULL pointer or not.\r
- */\r
- hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));\r
- if (hres) {\r
- ERR("Failed to load pointer cookie.\n");\r
- return hres;\r
- }\r
- if (cookie != 0x42424242) {\r
- /* we read a NULL ptr from the remote side */\r
- if (debugout) TRACE_(olerelay)("NULL");\r
- *arg = 0;\r
- return S_OK;\r
- }\r
- if (debugout) TRACE_(olerelay)("*");\r
- if (alloc) {\r
- /* Allocate space for the referenced struct */\r
- if (derefhere)\r
- *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc));\r
- }\r
- if (derefhere)\r
- return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, (LPDWORD)*arg, buf);\r
- else\r
- return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, arg, buf);\r
- }\r
- case VT_UNKNOWN:\r
- /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */\r
- if (alloc)\r
- *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));\r
- hres = S_OK;\r
- if (readit)\r
- hres = _unmarshal_interface(buf,&IID_IUnknown,(LPUNKNOWN*)arg);\r
- if (debugout)\r
- TRACE_(olerelay)("unk(%p)",arg);\r
- return hres;\r
- case VT_DISPATCH:\r
- hres = S_OK;\r
- if (readit)\r
- hres = _unmarshal_interface(buf,&IID_IDispatch,(LPUNKNOWN*)arg);\r
- if (debugout)\r
- TRACE_(olerelay)("idisp(%p)",arg);\r
- return hres;\r
- case VT_VOID:\r
- if (debugout) TRACE_(olerelay)("<void>");\r
- return S_OK;\r
- case VT_USERDEFINED: {\r
- ITypeInfo *tinfo2;\r
- TYPEATTR *tattr;\r
-\r
- hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);\r
- if (hres) {\r
- ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);\r
- return hres;\r
- }\r
- hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);\r
- if (hres) {\r
- ERR("Could not get typeattr in VT_USERDEFINED.\n");\r
- } else {\r
- switch (tattr->typekind) {\r
- case TKIND_DISPATCH:\r
- case TKIND_INTERFACE:\r
- if (readit)\r
- hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);\r
- break;\r
- case TKIND_RECORD: {\r
- int i;\r
-\r
- if (alloc)\r
- *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance);\r
-\r
- if (debugout) TRACE_(olerelay)("{");\r
- for (i=0;i<tattr->cVars;i++) {\r
- VARDESC *vdesc;\r
-\r
- hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);\r
- if (hres) {\r
- ERR("Could not get vardesc of %d\n",i);\r
- return hres;\r
- }\r
- hres = deserialize_param(\r
- tinfo2,\r
- readit,\r
- debugout,\r
- alloc,\r
- &vdesc->elemdescVar.tdesc,\r
- (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst),\r
- buf\r
- );\r
- if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(",");\r
- }\r
- if (buf->thisisiid && (tattr->cbSizeInstance==sizeof(GUID)))\r
- memcpy(&(buf->iid),(LPBYTE)*arg,sizeof(buf->iid));\r
- if (debugout) TRACE_(olerelay)("}");\r
- break;\r
- }\r
- default:\r
- ERR("Unhandled typekind %d\n",tattr->typekind);\r
- hres = E_FAIL;\r
- break;\r
- }\r
- }\r
- if (hres)\r
- ERR("failed to stuballoc in TKIND_RECORD.\n");\r
- ITypeInfo_Release(tinfo2);\r
- return hres;\r
- }\r
- case VT_CARRAY: {\r
- /* arg is pointing to the start of the array. */\r
- ARRAYDESC *adesc = tdesc->u.lpadesc;\r
- int arrsize,i;\r
- arrsize = 1;\r
- if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n");\r
- for (i=0;i<adesc->cDims;i++)\r
- arrsize *= adesc->rgbounds[i].cElements;\r
- for (i=0;i<arrsize;i++)\r
- deserialize_param(\r
- tinfo,\r
- readit,\r
- debugout,\r
- alloc,\r
- &adesc->tdescElem,\r
- (DWORD*)((LPBYTE)(arg)+i*_xsize(&adesc->tdescElem)),\r
- buf\r
- );\r
- return S_OK;\r
- }\r
- default:\r
- ERR("No handler for VT type %d!\n",tdesc->vt);\r
- return S_OK;\r
- }\r
- }\r
-}\r
-\r
-static HRESULT\r
-deserialize_LPVOID_ptr(\r
- ITypeInfo *tinfo,\r
- BOOL readit,\r
- BOOL debugout,\r
- BOOL alloc,\r
- TYPEDESC *tdesc,\r
- DWORD *arg,\r
- marshal_state *buf\r
-) {\r
- HRESULT hres;\r
- DWORD cookie;\r
-\r
- if ((tdesc->vt != VT_PTR) ||\r
- (tdesc->u.lptdesc->vt != VT_PTR) ||\r
- (tdesc->u.lptdesc->u.lptdesc->vt != VT_VOID)\r
- ) {\r
- FIXME("ppvObject not expressed as VT_PTR -> VT_PTR -> VT_VOID?\n");\r
- return E_FAIL;\r
- }\r
- if (alloc)\r
- *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPVOID));\r
- if (readit) {\r
- hres = xbuf_get(buf, (LPVOID)&cookie, sizeof(cookie));\r
- if (hres)\r
- return hres;\r
- if (cookie != 0x42424242) {\r
- *(DWORD*)*arg = 0;\r
- if (debugout) TRACE_(olerelay)("<lpvoid NULL>");\r
- return S_OK;\r
- }\r
- }\r
- if (readit) {\r
- hres = _unmarshal_interface(buf,&buf->iid,(LPUNKNOWN*)*arg);\r
- if (hres) {\r
- FIXME("_unmarshal_interface of %s , %p failed with %lx\n", debugstr_guid(&buf->iid), (LPUNKNOWN*)*arg, hres);\r
- return hres;\r
- }\r
- }\r
- if (debugout) TRACE_(olerelay)("ppv(%p)",(LPVOID)*arg);\r
- return S_OK;\r
-}\r
-\r
-static HRESULT\r
-deserialize_DISPPARAM_ptr(\r
- ITypeInfo *tinfo,\r
- BOOL readit,\r
- BOOL debugout,\r
- BOOL alloc,\r
- TYPEDESC *tdesc,\r
- DWORD *arg,\r
- marshal_state *buf)\r
-{\r
- DWORD cookie;\r
- DISPPARAMS *disps;\r
- HRESULT hres;\r
- int i;\r
-\r
- if ((tdesc->vt != VT_PTR) || (tdesc->u.lptdesc->vt != VT_USERDEFINED)) {\r
- FIXME("DISPPARAMS not expressed as VT_PTR -> VT_USERDEFINED?\n");\r
- return E_FAIL;\r
- }\r
- if (readit) {\r
- hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));\r
- if (hres)\r
- return hres;\r
- if (cookie == 0) {\r
- *arg = 0;\r
- if (debugout) TRACE_(olerelay)("<DISPPARAMS NULL>");\r
- return S_OK;\r
- }\r
- }\r
- if (alloc)\r
- *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPPARAMS));\r
- disps = (DISPPARAMS*)*arg;\r
- if (!readit)\r
- return S_OK;\r
- hres = xbuf_get(buf, (LPBYTE)&disps->cArgs, sizeof(disps->cArgs));\r
- if (hres)\r
- return hres;\r
- if (alloc)\r
- disps->rgvarg = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(VARIANT)*disps->cArgs);\r
- if (debugout) TRACE_(olerelay)("D{");\r
- for (i=0; i< disps->cArgs; i++) {\r
- TYPEDESC vdesc;\r
-\r
- vdesc.vt = VT_VARIANT;\r
- hres = deserialize_param(\r
- tinfo,\r
- readit,\r
- debugout,\r
- alloc,\r
- &vdesc,\r
- (DWORD*)(disps->rgvarg+i),\r
- buf\r
- );\r
- }\r
- if (debugout) TRACE_(olerelay)("}{");\r
- hres = xbuf_get(buf, (LPBYTE)&disps->cNamedArgs, sizeof(disps->cNamedArgs));\r
- if (hres)\r
- return hres;\r
- if (disps->cNamedArgs) {\r
- if (alloc)\r
- disps->rgdispidNamedArgs = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPID)*disps->cNamedArgs);\r
- for (i=0; i< disps->cNamedArgs; i++) {\r
- TYPEDESC vdesc;\r
-\r
- vdesc.vt = VT_UINT;\r
- hres = deserialize_param(\r
- tinfo,\r
- readit,\r
- debugout,\r
- alloc,\r
- &vdesc,\r
- (DWORD*)(disps->rgdispidNamedArgs+i),\r
- buf\r
- );\r
- if (debugout && i<(disps->cNamedArgs-1)) TRACE_(olerelay)(",");\r
- }\r
- }\r
- if (debugout) TRACE_(olerelay)("}");\r
- return S_OK;\r
-}\r
-\r
-/* Searches function, also in inherited interfaces */\r
-static HRESULT\r
-_get_funcdesc(\r
- ITypeInfo *tinfo, int iMethod, FUNCDESC **fdesc, BSTR *iname, BSTR *fname)\r
-{\r
- int i = 0, j = 0;\r
- HRESULT hres;\r
-\r
- if (fname) *fname = NULL;\r
- if (iname) *iname = NULL;\r
-\r
- while (1) {\r
- hres = ITypeInfo_GetFuncDesc(tinfo, i, fdesc);\r
- if (hres) {\r
- ITypeInfo *tinfo2;\r
- HREFTYPE href;\r
- TYPEATTR *attr;\r
-\r
- hres = ITypeInfo_GetTypeAttr(tinfo, &attr);\r
- if (hres) {\r
- ERR("GetTypeAttr failed with %lx\n",hres);\r
- return hres;\r
- }\r
- /* Not found, so look in inherited ifaces. */\r
- for (j=0;j<attr->cImplTypes;j++) {\r
- hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);\r
- if (hres) {\r
- ERR("Did not find a reftype for interface offset %d?\n",j);\r
- break;\r
- }\r
- hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);\r
- if (hres) {\r
- ERR("Did not find a typeinfo for reftype %ld?\n",href);\r
- continue;\r
- }\r
- hres = _get_funcdesc(tinfo2,iMethod,fdesc,iname,fname);\r
- ITypeInfo_Release(tinfo2);\r
- if (!hres) return S_OK;\r
- }\r
- return hres;\r
- }\r
- if (((*fdesc)->oVft/4) == iMethod) {\r
- if (fname)\r
- ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL);\r
- if (iname)\r
- ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL);\r
- return S_OK;\r
- }\r
- i++;\r
- }\r
-}\r
-\r
-static DWORD\r
-xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)\r
-{\r
- DWORD *args = ((DWORD*)&tpinfo)+1, *xargs;\r
- FUNCDESC *fdesc;\r
- HRESULT hres;\r
- int i, relaydeb = TRACE_ON(olerelay);\r
- marshal_state buf;\r
- RPCOLEMESSAGE msg;\r
- ULONG status;\r
- BSTR fname,iname;\r
- BSTR names[10];\r
- int nrofnames;\r
- int is_idispatch_getidsofnames = 0;\r
- DWORD remoteresult = 0;\r
-\r
- EnterCriticalSection(&tpinfo->crit);\r
-\r
- hres = _get_funcdesc(tpinfo->tinfo,method,&fdesc,&iname,&fname);\r
- if (hres) {\r
- ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);\r
- LeaveCriticalSection(&tpinfo->crit);\r
- return E_FAIL;\r
- }\r
-\r
- if (!tpinfo->chanbuf)\r
- {\r
- WARN("Tried to use disconnected proxy\n");\r
- LeaveCriticalSection(&tpinfo->crit);\r
- return RPC_E_DISCONNECTED;\r
- }\r
-\r
- if (relaydeb) {\r
- TRACE_(olerelay)("->");\r
- if (iname)\r
- TRACE_(olerelay)("%s:",relaystr(iname));\r
- if (fname)\r
- TRACE_(olerelay)("%s(%d)",relaystr(fname),method);\r
- else\r
- TRACE_(olerelay)("%d",method);\r
- TRACE_(olerelay)("(");\r
- }\r
- if (iname && fname && !lstrcmpW(iname,IDispatchW) && !lstrcmpW(fname,GetIDsOfNamesW))\r
- is_idispatch_getidsofnames = 1;\r
-\r
- if (iname) SysFreeString(iname);\r
- if (fname) SysFreeString(fname);\r
-\r
- memset(&buf,0,sizeof(buf));\r
- buf.iid = IID_IUnknown;\r
-\r
- /* Special IDispatch::GetIDsOfNames() serializer */\r
- if (is_idispatch_getidsofnames) {\r
- hres = serialize_IDispatch_GetIDsOfNames(TRUE,relaydeb,args,&buf);\r
- if (hres != S_OK) {\r
- FIXME("serialize of IDispatch::GetIDsOfNames failed!\n");\r
- return hres;\r
- }\r
- goto afterserialize;\r
- }\r
-\r
- /* special QueryInterface serialize */\r
- if (method == 0) {\r
- xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));\r
- if (relaydeb) TRACE_(olerelay)("riid=%s,[out])",debugstr_guid((REFIID)args[0]));\r
- goto afterserialize;\r
- }\r
-\r
- /* normal typelib driven serializing */\r
-\r
- /* Need them for hack below */\r
- memset(names,0,sizeof(names));\r
- if (ITypeInfo_GetNames(tpinfo->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))\r
- nrofnames = 0;\r
- if (nrofnames > sizeof(names)/sizeof(names[0]))\r
- ERR("Need more names!\n");\r
-\r
- xargs = args;\r
- for (i=0;i<fdesc->cParams;i++) {\r
- ELEMDESC *elem = fdesc->lprgelemdescParam+i;\r
- BOOL isserialized = FALSE;\r
- if (relaydeb) {\r
- if (i) TRACE_(olerelay)(",");\r
- if (i+1<nrofnames && names[i+1])\r
- TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
- }\r
- /* No need to marshal other data than FIN and any VT_PTR. */\r
- if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN) && (elem->tdesc.vt != VT_PTR)) {\r
- xargs+=_argsize(elem->tdesc.vt);\r
- if (relaydeb) TRACE_(olerelay)("[out]");\r
- continue;\r
- }\r
- if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
- /* If the parameter is 'riid', we use it as interface IID\r
- * for a later ppvObject serialization.\r
- */\r
- buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
-\r
- /* DISPPARAMS* needs special serializer */\r
- if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
- hres = serialize_DISPPARAM_ptr(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
- relaydeb,\r
- FALSE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- isserialized = TRUE;\r
- }\r
- if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
- hres = serialize_LPVOID_ptr(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
- relaydeb,\r
- FALSE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- if (hres == S_OK)\r
- isserialized = TRUE;\r
- }\r
- }\r
- if (!isserialized)\r
- hres = serialize_param(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
- relaydeb,\r
- FALSE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
-\r
- if (hres) {\r
- ERR("Failed to serialize param, hres %lx\n",hres);\r
- break;\r
- }\r
- xargs+=_argsize(elem->tdesc.vt);\r
- }\r
- if (relaydeb) TRACE_(olerelay)(")");\r
-\r
-afterserialize:\r
- memset(&msg,0,sizeof(msg));\r
- msg.cbBuffer = buf.curoff;\r
- msg.iMethod = method;\r
- hres = IRpcChannelBuffer_GetBuffer(tpinfo->chanbuf,&msg,&(tpinfo->iid));\r
- if (hres) {\r
- ERR("RpcChannelBuffer GetBuffer failed, %lx\n",hres);\r
- LeaveCriticalSection(&tpinfo->crit);\r
- return hres;\r
- }\r
- memcpy(msg.Buffer,buf.base,buf.curoff);\r
- if (relaydeb) TRACE_(olerelay)("\n");\r
- hres = IRpcChannelBuffer_SendReceive(tpinfo->chanbuf,&msg,&status);\r
- if (hres) {\r
- ERR("RpcChannelBuffer SendReceive failed, %lx\n",hres);\r
- LeaveCriticalSection(&tpinfo->crit);\r
- return hres;\r
- }\r
-\r
- if (relaydeb) TRACE_(olerelay)(" status = %08lx (",status);\r
- if (buf.base)\r
- buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);\r
- else\r
- buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);\r
- buf.size = msg.cbBuffer;\r
- memcpy(buf.base,msg.Buffer,buf.size);\r
- buf.curoff = 0;\r
-\r
- /* Special IDispatch::GetIDsOfNames() deserializer */\r
- if (is_idispatch_getidsofnames) {\r
- hres = deserialize_IDispatch_GetIDsOfNames(FALSE,relaydeb,args,&buf);\r
- if (hres != S_OK) {\r
- FIXME("deserialize of IDispatch::GetIDsOfNames failed!\n");\r
- return hres;\r
- }\r
- goto after_deserialize;\r
- }\r
- /* Special QueryInterface deserializer */\r
- if (method == 0) {\r
- _unmarshal_interface(&buf,(REFIID)args[0],(LPUNKNOWN*)args[1]);\r
- if (relaydeb) TRACE_(olerelay)("[in],%p",*((DWORD**)args[1]));\r
- goto after_deserialize;\r
- }\r
-\r
- /* generic deserializer using typelib description */\r
- xargs = args;\r
- status = S_OK;\r
- for (i=0;i<fdesc->cParams;i++) {\r
- ELEMDESC *elem = fdesc->lprgelemdescParam+i;\r
- BOOL isdeserialized = FALSE;\r
-\r
- if (relaydeb) {\r
- if (i) TRACE_(olerelay)(",");\r
- if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
- }\r
- /* No need to marshal other data than FOUT and any VT_PTR */\r
- if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {\r
- xargs += _argsize(elem->tdesc.vt);\r
- if (relaydeb) TRACE_(olerelay)("[in]");\r
- continue;\r
- }\r
- if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
- /* If the parameter is 'riid', we use it as interface IID\r
- * for a later ppvObject serialization.\r
- */\r
- buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
-\r
- /* deserialize DISPPARAM */\r
- if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
- hres = deserialize_DISPPARAM_ptr(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
- relaydeb,\r
- FALSE,\r
- &(elem->tdesc),\r
- xargs,\r
- &buf\r
- );\r
- if (hres) {\r
- ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres);\r
- break;\r
- }\r
- isdeserialized = TRUE;\r
- }\r
- if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
- hres = deserialize_LPVOID_ptr(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
- relaydeb,\r
- FALSE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- if (hres == S_OK)\r
- isdeserialized = TRUE;\r
- }\r
- }\r
- if (!isdeserialized)\r
- hres = deserialize_param(\r
- tpinfo->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
- relaydeb,\r
- FALSE,\r
- &(elem->tdesc),\r
- xargs,\r
- &buf\r
- );\r
- if (hres) {\r
- ERR("Failed to unmarshall param, hres %lx\n",hres);\r
- status = hres;\r
- break;\r
- }\r
- xargs += _argsize(elem->tdesc.vt);\r
- }\r
-after_deserialize:\r
- hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));\r
- if (hres != S_OK)\r
- return hres;\r
- if (relaydeb) TRACE_(olerelay)(") = %08lx\n", remoteresult);\r
-\r
- if (status != S_OK) /* OLE/COM internal error */\r
- return status;\r
-\r
- HeapFree(GetProcessHeap(),0,buf.base);\r
- LeaveCriticalSection(&tpinfo->crit);\r
- return remoteresult;\r
-}\r
-\r
-HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)\r
-{\r
- TMProxyImpl *proxy = (TMProxyImpl *)iface;\r
-\r
- TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);\r
-\r
- if (proxy->outerunknown)\r
- return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);\r
-\r
- FIXME("No interface\n");\r
- return E_NOINTERFACE;\r
-}\r
-\r
-ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)\r
-{\r
- TMProxyImpl *proxy = (TMProxyImpl *)iface;\r
-\r
- TRACE("\n");\r
-\r
- if (proxy->outerunknown)\r
- return IUnknown_AddRef(proxy->outerunknown);\r
-\r
- return 2; /* FIXME */\r
-}\r
-\r
-ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)\r
-{\r
- TMProxyImpl *proxy = (TMProxyImpl *)iface;\r
-\r
- TRACE("\n");\r
-\r
- if (proxy->outerunknown)\r
- return IUnknown_Release(proxy->outerunknown);\r
-\r
- return 1; /* FIXME */\r
-}\r
-\r
-static HRESULT WINAPI\r
-PSFacBuf_CreateProxy(\r
- LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,\r
- IRpcProxyBuffer **ppProxy, LPVOID *ppv)\r
-{\r
- HRESULT hres;\r
- ITypeInfo *tinfo;\r
- int i, nroffuncs;\r
- FUNCDESC *fdesc;\r
- TMProxyImpl *proxy;\r
-\r
- TRACE("(...%s...)\n",debugstr_guid(riid));\r
- hres = _get_typeinfo_for_iid(riid,&tinfo);\r
- if (hres) {\r
- ERR("No typeinfo for %s?\n",debugstr_guid(riid));\r
- return hres;\r
- }\r
- nroffuncs = _nroffuncs(tinfo);\r
- proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));\r
- if (!proxy) return E_OUTOFMEMORY;\r
-\r
- assert(sizeof(TMAsmProxy) == 12);\r
-\r
- proxy->outerunknown = pUnkOuter;\r
- proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
- if (!proxy->asmstubs) {\r
- ERR("Could not commit pages for proxy thunks\n");\r
- CoTaskMemFree(proxy);\r
- return E_OUTOFMEMORY;\r
- }\r
-\r
- InitializeCriticalSection(&proxy->crit);\r
-\r
- proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);\r
- for (i=0;i<nroffuncs;i++) {\r
- TMAsmProxy *xasm = proxy->asmstubs+i;\r
-\r
- switch (i) {\r
- case 0:\r
- proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;\r
- break;\r
- case 1:\r
- proxy->lpvtbl[i] = ProxyIUnknown_AddRef;\r
- break;\r
- case 2:\r
- proxy->lpvtbl[i] = ProxyIUnknown_Release;\r
- break;\r
- default: {\r
- int j;\r
- /* nrofargs without This */\r
- int nrofargs;\r
- hres = _get_funcdesc(tinfo,i,&fdesc,NULL,NULL);\r
- if (hres) {\r
- ERR("GetFuncDesc %lx should not fail here.\n",hres);\r
- return hres;\r
- }\r
- /* some args take more than 4 byte on the stack */\r
- nrofargs = 0;\r
- for (j=0;j<fdesc->cParams;j++)\r
- nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);\r
-\r
- if (fdesc->callconv != CC_STDCALL) {\r
- ERR("calling convention is not stdcall????\n");\r
- return E_FAIL;\r
- }\r
-/* popl %eax - return ptr\r
- * pushl <nr>\r
- * pushl %eax\r
- * call xCall\r
- * lret <nr> (+4)\r
- *\r
- *\r
- * arg3 arg2 arg1 <method> <returnptr>\r
- */\r
- xasm->popleax = 0x58;\r
- xasm->pushlval = 0x6a;\r
- xasm->nr = i;\r
- xasm->pushleax = 0x50;\r
- xasm->lcall = 0xe8; /* relative jump */\r
- xasm->xcall = (DWORD)xCall;\r
- xasm->xcall -= (DWORD)&(xasm->lret);\r
- xasm->lret = 0xc2;\r
- xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */\r
- proxy->lpvtbl[i] = xasm;\r
- break;\r
- }\r
- }\r
- }\r
- proxy->lpvtbl2 = &tmproxyvtable;\r
- /* 1 reference for the proxy and 1 for the object */\r
- proxy->ref = 2;\r
- proxy->tinfo = tinfo;\r
- memcpy(&proxy->iid,riid,sizeof(*riid));\r
- proxy->chanbuf = 0;\r
- *ppv = (LPVOID)proxy;\r
- *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2);\r
- return S_OK;\r
-}\r
-\r
-typedef struct _TMStubImpl {\r
- IRpcStubBufferVtbl *lpvtbl;\r
- ULONG ref;\r
-\r
- LPUNKNOWN pUnk;\r
- ITypeInfo *tinfo;\r
- IID iid;\r
-} TMStubImpl;\r
-\r
-static HRESULT WINAPI\r
-TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv)\r
-{\r
- if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){\r
- *ppv = (LPVOID)iface;\r
- IRpcStubBuffer_AddRef(iface);\r
- return S_OK;\r
- }\r
- FIXME("%s, not supported IID.\n",debugstr_guid(riid));\r
- return E_NOINTERFACE;\r
-}\r
-\r
-static ULONG WINAPI\r
-TMStubImpl_AddRef(LPRPCSTUBBUFFER iface)\r
-{\r
- TMStubImpl *This = (TMStubImpl *)iface;\r
- ULONG refCount = InterlockedIncrement(&This->ref);\r
- \r
- TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1);\r
-\r
- return refCount;\r
-}\r
-\r
-static ULONG WINAPI\r
-TMStubImpl_Release(LPRPCSTUBBUFFER iface)\r
-{\r
- TMStubImpl *This = (TMStubImpl *)iface;\r
- ULONG refCount = InterlockedDecrement(&This->ref);\r
-\r
- TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1);\r
-\r
- if (!refCount)\r
- {\r
- IRpcStubBuffer_Disconnect(iface);\r
- CoTaskMemFree(This);\r
- }\r
- return refCount;\r
-}\r
-\r
-static HRESULT WINAPI\r
-TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer)\r
-{\r
- TMStubImpl *This = (TMStubImpl *)iface;\r
-\r
- TRACE("(%p)->(%p)\n", This, pUnkServer);\r
-\r
- IUnknown_AddRef(pUnkServer);\r
- This->pUnk = pUnkServer;\r
- return S_OK;\r
-}\r
-\r
-static void WINAPI\r
-TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)\r
-{\r
- TMStubImpl *This = (TMStubImpl *)iface;\r
-\r
- TRACE("(%p)->()\n", This);\r
-\r
- IUnknown_Release(This->pUnk);\r
- This->pUnk = NULL;\r
- return;\r
-}\r
-\r
-static HRESULT WINAPI\r
-TMStubImpl_Invoke(\r
- LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf)\r
-{\r
- int i;\r
- FUNCDESC *fdesc;\r
- TMStubImpl *This = (TMStubImpl *)iface;\r
- HRESULT hres;\r
- DWORD *args, res, *xargs, nrofargs;\r
- marshal_state buf;\r
- int nrofnames;\r
- BSTR names[10];\r
- BSTR fname = NULL,iname = NULL;\r
- BOOL is_idispatch_getidsofnames = 0;\r
-\r
- memset(&buf,0,sizeof(buf));\r
- buf.size = xmsg->cbBuffer;\r
- buf.base = xmsg->Buffer;\r
- buf.curoff = 0;\r
- buf.iid = IID_IUnknown;\r
-\r
- TRACE("...\n");\r
- if (xmsg->iMethod == 0) { /* QI */\r
- IID xiid;\r
- /* in: IID, out: <iface> */\r
-\r
- xbuf_get(&buf,(LPBYTE)&xiid,sizeof(xiid));\r
- buf.curoff = 0;\r
- hres = _marshal_interface(&buf,&xiid,This->pUnk);\r
- xmsg->Buffer = buf.base; /* Might have been reallocated */\r
- xmsg->cbBuffer = buf.size;\r
- return hres;\r
- }\r
- hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,&iname,&fname);\r
- if (hres) {\r
- ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);\r
- return hres;\r
- }\r
-\r
- if (iname && fname && !lstrcmpW(iname, IDispatchW) && !lstrcmpW(fname, GetIDsOfNamesW))\r
- is_idispatch_getidsofnames = 1;\r
-\r
- if (iname) SysFreeString (iname);\r
- if (fname) SysFreeString (fname);\r
-\r
- /* Need them for hack below */\r
- memset(names,0,sizeof(names));\r
- ITypeInfo_GetNames(This->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);\r
- if (nrofnames > sizeof(names)/sizeof(names[0])) {\r
- ERR("Need more names!\n");\r
- }\r
-\r
- /*dump_FUNCDESC(fdesc);*/\r
- nrofargs = 0;\r
- for (i=0;i<fdesc->cParams;i++)\r
- nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);\r
- args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));\r
- if (!args) return E_OUTOFMEMORY;\r
-\r
- if (is_idispatch_getidsofnames) {\r
- hres = deserialize_IDispatch_GetIDsOfNames(TRUE,FALSE,args+1,&buf);\r
- if (hres != S_OK) {\r
- FIXME("deserialize_IDispatch_GetIDsOfNames failed!\n");\r
- return hres;\r
- }\r
- xargs = args+1+5;\r
- goto afterdeserialize;\r
- }\r
-\r
- /* Allocate all stuff used by call. */\r
- xargs = args+1;\r
- for (i=0;i<fdesc->cParams;i++) {\r
- ELEMDESC *elem = fdesc->lprgelemdescParam+i;\r
- BOOL isdeserialized = FALSE;\r
-\r
- if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
- /* If the parameter is 'riid', we use it as interface IID\r
- * for a later ppvObject serialization.\r
- */\r
- buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
-\r
- /* deserialize DISPPARAM */\r
- if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
- hres = deserialize_DISPPARAM_ptr(\r
- This->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
- FALSE,\r
- TRUE,\r
- &(elem->tdesc),\r
- xargs,\r
- &buf\r
- );\r
- if (hres) {\r
- ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres);\r
- break;\r
- }\r
- isdeserialized = TRUE;\r
- }\r
- if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
- hres = deserialize_LPVOID_ptr(\r
- This->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
- FALSE,\r
- TRUE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- if (hres == S_OK)\r
- isdeserialized = TRUE;\r
- }\r
- }\r
- if (!isdeserialized)\r
- hres = deserialize_param(\r
- This->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
- FALSE,\r
- TRUE,\r
- &(elem->tdesc),\r
- xargs,\r
- &buf\r
- );\r
- xargs += _argsize(elem->tdesc.vt);\r
- if (hres) {\r
- ERR("Failed to deserialize param %s, hres %lx\n",relaystr(names[i+1]),hres);\r
- break;\r
- }\r
- }\r
-afterdeserialize:\r
- hres = IUnknown_QueryInterface(This->pUnk,&(This->iid),(LPVOID*)&(args[0]));\r
- if (hres) {\r
- ERR("Does not support iface %s, returning %lx\n",debugstr_guid(&(This->iid)), hres);\r
- return hres;\r
- }\r
- res = _invoke(\r
- (*((FARPROC**)args[0]))[fdesc->oVft/4],\r
- fdesc->callconv,\r
- (xargs-args),\r
- args\r
- );\r
- IUnknown_Release((LPUNKNOWN)args[0]);\r
- buf.curoff = 0;\r
-\r
- /* special IDispatch::GetIDsOfNames serializer */\r
- if (is_idispatch_getidsofnames) {\r
- hres = serialize_IDispatch_GetIDsOfNames(FALSE,FALSE,args+1,&buf);\r
- if (hres != S_OK) {\r
- FIXME("serialize of IDispatch::GetIDsOfNames failed!\n");\r
- return hres;\r
- }\r
- goto afterserialize;\r
- }\r
- xargs = args+1;\r
- for (i=0;i<fdesc->cParams;i++) {\r
- ELEMDESC *elem = fdesc->lprgelemdescParam+i;\r
- BOOL isserialized = FALSE;\r
-\r
- if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
- /* If the parameter is 'riid', we use it as interface IID\r
- * for a later ppvObject serialization.\r
- */\r
- buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
-\r
- /* DISPPARAMS* needs special serializer */\r
- if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
- hres = serialize_DISPPARAM_ptr(\r
- This->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
- FALSE,\r
- TRUE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- isserialized = TRUE;\r
- }\r
- if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
- hres = serialize_LPVOID_ptr(\r
- This->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
- FALSE,\r
- TRUE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- if (hres == S_OK)\r
- isserialized = TRUE;\r
- }\r
- }\r
- if (!isserialized)\r
- hres = serialize_param(\r
- This->tinfo,\r
- elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
- FALSE,\r
- TRUE,\r
- &elem->tdesc,\r
- xargs,\r
- &buf\r
- );\r
- xargs += _argsize(elem->tdesc.vt);\r
- if (hres) {\r
- ERR("Failed to stuballoc param, hres %lx\n",hres);\r
- break;\r
- }\r
- }\r
-afterserialize:\r
- hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));\r
- if (hres != S_OK)\r
- return hres;\r
- \r
- /* might need to use IRpcChannelBuffer_GetBuffer ? */\r
- xmsg->cbBuffer = buf.curoff;\r
- xmsg->Buffer = buf.base;\r
- HeapFree(GetProcessHeap(),0,args);\r
- return S_OK;\r
-}\r
-\r
-static LPRPCSTUBBUFFER WINAPI\r
-TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {\r
- FIXME("Huh (%s)?\n",debugstr_guid(riid));\r
- return NULL;\r
-}\r
-\r
-static ULONG WINAPI\r
-TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {\r
- TMStubImpl *This = (TMStubImpl *)iface;\r
-\r
- return This->ref; /*FIXME? */\r
-}\r
-\r
-static HRESULT WINAPI\r
-TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {\r
- return E_NOTIMPL;\r
-}\r
-\r
-static void WINAPI\r
-TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {\r
- return;\r
-}\r
-\r
-IRpcStubBufferVtbl tmstubvtbl = {\r
- TMStubImpl_QueryInterface,\r
- TMStubImpl_AddRef,\r
- TMStubImpl_Release,\r
- TMStubImpl_Connect,\r
- TMStubImpl_Disconnect,\r
- TMStubImpl_Invoke,\r
- TMStubImpl_IsIIDSupported,\r
- TMStubImpl_CountRefs,\r
- TMStubImpl_DebugServerQueryInterface,\r
- TMStubImpl_DebugServerRelease\r
-};\r
-\r
-static HRESULT WINAPI\r
-PSFacBuf_CreateStub(\r
- LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,\r
- IRpcStubBuffer** ppStub\r
-) {\r
- HRESULT hres;\r
- ITypeInfo *tinfo;\r
- TMStubImpl *stub;\r
-\r
- TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);\r
- hres = _get_typeinfo_for_iid(riid,&tinfo);\r
- if (hres) {\r
- ERR("No typeinfo for %s?\n",debugstr_guid(riid));\r
- return hres;\r
- }\r
- stub = CoTaskMemAlloc(sizeof(TMStubImpl));\r
- if (!stub)\r
- return E_OUTOFMEMORY;\r
- stub->lpvtbl = &tmstubvtbl;\r
- stub->ref = 1;\r
- stub->tinfo = tinfo;\r
- memcpy(&(stub->iid),riid,sizeof(*riid));\r
- hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);\r
- *ppStub = (LPRPCSTUBBUFFER)stub;\r
- TRACE("IRpcStubBuffer: %p\n", stub);\r
- if (hres)\r
- ERR("Connect to pUnkServer failed?\n");\r
- return hres;\r
-}\r
-\r
-static IPSFactoryBufferVtbl psfacbufvtbl = {\r
- PSFacBuf_QueryInterface,\r
- PSFacBuf_AddRef,\r
- PSFacBuf_Release,\r
- PSFacBuf_CreateProxy,\r
- PSFacBuf_CreateStub\r
-};\r
-\r
-/* This is the whole PSFactoryBuffer object, just the vtableptr */\r
-static IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;\r
-\r
-/***********************************************************************\r
- * DllGetClassObject [OLE32.63]\r
- */\r
-HRESULT WINAPI\r
-TypeLibFac_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)\r
-{\r
- if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {\r
- *ppv = &lppsfac;\r
- return S_OK;\r
- }\r
- return E_NOINTERFACE;\r
-}\r
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define COBJMACROS
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "winuser.h"
+
+#include "ole2.h"
+#include "typelib.h"
+#include "wine/debug.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);
+
+#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
+
+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_add(marshal_state *buf, LPBYTE stuff, DWORD size) {
+ while (buf->size - buf->curoff < size) {
+ if (buf->base) {
+ buf->size += 100;
+ buf->base = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,buf->base,buf->size);
+ if (!buf->base)
+ return E_OUTOFMEMORY;
+ } else {
+ buf->base = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,32);
+ buf->size = 32;
+ if (!buf->base)
+ return E_OUTOFMEMORY;
+ }
+ }
+ 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 %lx\n",hres);
+ return hres;
+ }
+
+ hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res);
+ if (hres) {
+ ERR("stream write %lx\n",hres);
+ return hres;
+ }
+
+ memset(&seekto,0,sizeof(seekto));
+ hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
+ if (hres) {
+ ERR("Failed Seek %lx\n",hres);
+ return hres;
+ }
+
+ hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk);
+ if (hres) {
+ ERR("Unmarshalling interface %s failed with %lx\n",debugstr_guid(riid),hres);
+ 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.
+ */
+ ERR("pUnk is NULL?\n");
+ xsize = 0;
+ return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
+ }
+
+ hres = E_FAIL;
+
+ TRACE("...%s...\n",debugstr_guid(riid));
+
+ hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
+ if (hres) {
+ ERR("Stream create failed %lx\n",hres);
+ goto fail;
+ }
+
+ hres = CoMarshalInterface(pStm,riid,pUnk,0,NULL,0);
+ if (hres) {
+ ERR("Marshalling interface %s failed with %lx\n", debugstr_guid(riid), hres);
+ goto fail;
+ }
+
+ hres = IStream_Stat(pStm,&ststg,0);
+ 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 %lx\n",hres);
+ goto fail;
+ }
+
+ hres = IStream_Read(pStm,tempbuf,ststg.cbSize.u.LowPart,&res);
+ if (hres) {
+ ERR("Failed Read %lx\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) IUnknown_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 = (LPVOID)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; }
+
+static HRESULT
+_get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
+ HRESULT hres;
+ HKEY ikey;
+ char tlguid[200],typelibkey[300],interfacekey[300],ver[100];
+ char tlfn[260];
+ OLECHAR tlfnW[260];
+ DWORD tlguidlen, verlen, type;
+ LONG tlfnlen;
+ ITypeLib *tl;
+
+ sprintf( interfacekey, "Interface\\{%08lx-%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]
+ );
+
+ if (RegOpenKeyA(HKEY_CLASSES_ROOT,interfacekey,&ikey)) {
+ ERR("No %s key found.\n",interfacekey);
+ return E_FAIL;
+ }
+ type = (1<<REG_SZ);
+ tlguidlen = sizeof(tlguid);
+ if (RegQueryValueExA(ikey,NULL,NULL,&type,(LPBYTE)tlguid,&tlguidlen)) {
+ ERR("Getting typelib guid failed.\n");
+ RegCloseKey(ikey);
+ return E_FAIL;
+ }
+ type = (1<<REG_SZ);
+ 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\\win32",tlguid,ver);
+ tlfnlen = sizeof(tlfn);
+ if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) {
+ ERR("Could not get typelib fn?\n");
+ return E_FAIL;
+ }
+ MultiByteToWideChar(CP_ACP, 0, tlfn, -1, tlfnW, -1);
+ hres = LoadTypeLib(tlfnW,&tl);
+ if (hres) {
+ ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid));
+ return hres;
+ }
+ hres = ITypeLib_GetTypeInfoOfGuid(tl,riid,ti);
+ if (hres) {
+ ERR("typelib does not contain info for %s?\n",debugstr_guid(riid));
+ ITypeLib_Release(tl);
+ return hres;
+ }
+ /* FIXME: do this? ITypeLib_Release(tl); */
+ return hres;
+}
+
+/* Determine nr of functions. Since we use the toplevel interface and all
+ * inherited ones have lower numbers, we are ok to not to descent into
+ * the inheritance tree I think.
+ */
+static int _nroffuncs(ITypeInfo *tinfo) {
+ int n, max = 0;
+ const FUNCDESC *fdesc;
+ HRESULT hres;
+
+ n=0;
+ while (1) {
+ hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo,n,&fdesc);
+ if (hres)
+ return max+1;
+ if (fdesc->oVft/4 > max)
+ max = fdesc->oVft/4;
+ n++;
+ }
+ /*NOTREACHED*/
+}
+
+#ifdef __i386__
+
+#include "pshpack1.h"
+
+typedef struct _TMAsmProxy {
+ BYTE popleax;
+ BYTE pushlval;
+ BYTE nr;
+ BYTE pushleax;
+ BYTE lcall;
+ DWORD xcall;
+ BYTE lret;
+ WORD bytestopop;
+} 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;
+ const IRpcProxyBufferVtbl *lpvtbl2;
+ LONG ref;
+
+ TMAsmProxy *asmstubs;
+ ITypeInfo* tinfo;
+ IRpcChannelBuffer* chanbuf;
+ IID iid;
+ CRITICAL_SECTION crit;
+ IUnknown *outerunknown;
+ IDispatch *dispatch;
+} TMProxyImpl;
+
+static HRESULT WINAPI
+TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv)
+{
+ TRACE("()\n");
+ if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) {
+ *ppv = (LPVOID)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)
+{
+ ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
+ ULONG refCount = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p)->(ref before=%lu)\n",This, refCount - 1);
+
+ return refCount;
+}
+
+static ULONG WINAPI
+TMProxyImpl_Release(LPRPCPROXYBUFFER iface)
+{
+ ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
+ ULONG refCount = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p)->(ref before=%lu)\n",This, refCount + 1);
+
+ if (!refCount)
+ {
+ if (This->dispatch) IDispatch_Release(This->dispatch);
+ DeleteCriticalSection(&This->crit);
+ if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf);
+ VirtualFree(This->asmstubs, 0, MEM_RELEASE);
+ CoTaskMemFree(This);
+ }
+ return refCount;
+}
+
+static HRESULT WINAPI
+TMProxyImpl_Connect(
+ LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer)
+{
+ ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
+
+ TRACE("(%p)\n", pRpcChannelBuffer);
+
+ EnterCriticalSection(&This->crit);
+
+ IRpcChannelBuffer_AddRef(pRpcChannelBuffer);
+ This->chanbuf = pRpcChannelBuffer;
+
+ LeaveCriticalSection(&This->crit);
+
+ return S_OK;
+}
+
+static void WINAPI
+TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface)
+{
+ ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
+
+ TRACE("()\n");
+
+ EnterCriticalSection(&This->crit);
+
+ IRpcChannelBuffer_Release(This->chanbuf);
+ This->chanbuf = NULL;
+
+ LeaveCriticalSection(&This->crit);
+}
+
+
+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. */
+int
+_argsize(DWORD vt) {
+ switch (vt) {
+ 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_VARIANT:
+ return (sizeof(VARIANT)+3)/sizeof(DWORD);
+ default:
+ return 1;
+ }
+}
+
+static int
+_xsize(TYPEDESC *td) {
+ switch (td->vt) {
+ case VT_DATE:
+ return sizeof(DATE);
+ case VT_VARIANT:
+ return sizeof(VARIANT)+3;
+ case VT_CARRAY: {
+ int i, arrsize = 1;
+ ARRAYDESC *adesc = td->u.lpadesc;
+
+ for (i=0;i<adesc->cDims;i++)
+ arrsize *= adesc->rgbounds[i].cElements;
+ return arrsize*_xsize(&adesc->tdescElem);
+ }
+ case VT_UI8:
+ case VT_I8:
+ return 8;
+ case VT_UI2:
+ case VT_I2:
+ return 2;
+ case VT_UI1:
+ case VT_I1:
+ return 1;
+ default:
+ return 4;
+ }
+}
+
+static HRESULT
+serialize_param(
+ ITypeInfo *tinfo,
+ BOOL writeit,
+ BOOL debugout,
+ BOOL dealloc,
+ TYPEDESC *tdesc,
+ DWORD *arg,
+ marshal_state *buf)
+{
+ HRESULT hres = S_OK;
+
+ TRACE("(tdesc.vt %d)\n",tdesc->vt);
+
+ switch (tdesc->vt) {
+ case VT_EMPTY: /* nothing. empty variant for instance */
+ return S_OK;
+ case VT_I8:
+ case VT_UI8:
+ hres = S_OK;
+ if (debugout) TRACE_(olerelay)("%lx%lx",arg[0],arg[1]);
+ if (writeit)
+ hres = xbuf_add(buf,(LPBYTE)arg,8);
+ return hres;
+ case VT_BOOL:
+ case VT_ERROR:
+ case VT_UINT:
+ case VT_I4:
+ case VT_R4:
+ case VT_UI4:
+ hres = S_OK;
+ if (debugout) TRACE_(olerelay)("%lx",*arg);
+ if (writeit)
+ hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
+ return hres;
+ case VT_I2:
+ case VT_UI2:
+ hres = S_OK;
+ if (debugout) TRACE_(olerelay)("%04lx",*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)("%02lx",*arg & 0xff);
+ if (writeit)
+ hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
+ return hres;
+ case VT_I4|VT_BYREF:
+ hres = S_OK;
+ if (debugout) TRACE_(olerelay)("&0x%lx",*arg);
+ if (writeit)
+ hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD));
+ /* do not dealloc at this time */
+ return hres;
+ case VT_VARIANT: {
+ TYPEDESC tdesc2;
+ VARIANT *vt = (VARIANT*)arg;
+ DWORD vttype = V_VT(vt);
+
+ if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype);
+ tdesc2.vt = vttype;
+ if (writeit) {
+ hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
+ if (hres) return hres;
+ }
+ /* need to recurse since we need to free the stuff */
+ hres = serialize_param(tinfo,writeit,debugout,dealloc,&tdesc2,(DWORD*)&(V_I4(vt)),buf);
+ if (debugout) TRACE_(olerelay)(")");
+ return hres;
+ }
+ case VT_BSTR|VT_BYREF: {
+ if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>");
+ if (writeit) {
+ /* ptr to ptr to magic widestring, basically */
+ BSTR *bstr = (BSTR *) *arg;
+ DWORD len;
+ if (!*bstr) {
+ /* -1 means "null string" which is equivalent to empty string */
+ len = -1;
+ hres = xbuf_add(buf, (LPBYTE)&len,sizeof(DWORD));
+ if (hres) return hres;
+ } else {
+ len = *((DWORD*)*bstr-1)/sizeof(WCHAR);
+ hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
+ if (hres) return hres;
+ hres = xbuf_add(buf,(LPBYTE)*bstr,len * sizeof(WCHAR));
+ if (hres) return hres;
+ }
+ }
+
+ if (dealloc && arg) {
+ BSTR *str = *((BSTR **)arg);
+ SysFreeString(*str);
+ }
+ return S_OK;
+ }
+
+ case VT_BSTR: {
+ if (debugout) {
+ if (*arg)
+ TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg));
+ else
+ TRACE_(olerelay)("<bstr NULL>");
+ }
+ if (writeit) {
+ BSTR bstr = (BSTR)*arg;
+ DWORD len;
+ if (!bstr) {
+ len = -1;
+ hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
+ if (hres) return hres;
+ } else {
+ len = *((DWORD*)bstr-1)/sizeof(WCHAR);
+ hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
+ if (hres) return hres;
+ hres = xbuf_add(buf,(LPBYTE)bstr,len * sizeof(WCHAR));
+ if (hres) return hres;
+ }
+ }
+
+ if (dealloc && arg)
+ SysFreeString((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 %lx for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
+ return hres;
+ }
+ ITypeInfo_GetTypeAttr(tinfo2,&tattr);
+ switch (tattr->typekind) {
+ case TKIND_ENUM: /* confirmed */
+ case TKIND_RECORD: /* FIXME: mostly untested */
+ derefhere=TRUE;
+ break;
+ case TKIND_ALIAS: /* FIXME: untested */
+ 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_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%lx)",*arg);
+ if (writeit)
+ hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg);
+ return hres;
+ case VT_DISPATCH:
+ if (debugout) TRACE_(olerelay)("idisp(0x%lx)",*arg);
+ if (writeit)
+ hres = _marshal_interface(buf,&IID_IDispatch,(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 %lx 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 = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
+ if (hres) {
+ ERR("Could not get vardesc of %d\n",i);
+ return hres;
+ }
+ /* Need them for hack below */
+ /*
+ memset(names,0,sizeof(names));
+ hres = ITypeInfo_GetNames(tinfo2,vdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
+ if (nrofnames > sizeof(names)/sizeof(names[0])) {
+ ERR("Need more names!\n");
+ }
+ if (!hres && debugout)
+ TRACE_(olerelay)("%s=",relaystr(names[0]));
+ */
+ 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:
+ return serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf);
+ case TKIND_ENUM:
+ hres = S_OK;
+ if (debugout) TRACE_(olerelay)("%lx",*arg);
+ if (writeit)
+ hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
+ return hres;
+ default:
+ FIXME("Unhandled typekind %d\n",tattr->typekind);
+ hres = E_FAIL;
+ break;
+ }
+ 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)("[%ld]",adesc->rgbounds[i].cElements);
+ arrsize *= adesc->rgbounds[i].cElements;
+ }
+ if (debugout) TRACE_(olerelay)("(vt %d)",adesc->tdescElem.vt);
+ if (debugout) TRACE_(olerelay)("[");
+ for (i=0;i<arrsize;i++) {
+ hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);
+ if (hres)
+ return hres;
+ if (debugout && (i<arrsize-1)) TRACE_(olerelay)(",");
+ }
+ if (debugout) TRACE_(olerelay)("]");
+ 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;
+
+ TRACE("vt %d at %p\n",tdesc->vt,arg);
+
+ while (1) {
+ switch (tdesc->vt) {
+ case VT_EMPTY:
+ if (debugout) TRACE_(olerelay)("<empty>");
+ return S_OK;
+ case VT_NULL:
+ if (debugout) TRACE_(olerelay)("<null>");
+ return S_OK;
+ case VT_VARIANT: {
+ VARIANT *vt = (VARIANT*)arg;
+
+ if (readit) {
+ DWORD vttype;
+ TYPEDESC tdesc2;
+ hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype));
+ if (hres) {
+ FIXME("vt type not read?\n");
+ return hres;
+ }
+ memset(&tdesc2,0,sizeof(tdesc2));
+ tdesc2.vt = vttype;
+ V_VT(vt) = vttype;
+ if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype);
+ hres = deserialize_param(tinfo, readit, debugout, alloc, &tdesc2, (DWORD*)&(V_I4(vt)), buf);
+ TRACE_(olerelay)(")");
+ return hres;
+ } else {
+ VariantInit(vt);
+ return S_OK;
+ }
+ }
+ case VT_I8:
+ case VT_UI8:
+ if (readit) {
+ hres = xbuf_get(buf,(LPBYTE)arg,8);
+ if (hres) ERR("Failed to read integer 8 byte\n");
+ }
+ if (debugout) TRACE_(olerelay)("%lx%lx",arg[0],arg[1]);
+ return hres;
+ case VT_ERROR:
+ case VT_BOOL:
+ case VT_I4:
+ 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)("%lx",*arg);
+ return hres;
+ case VT_I2:
+ case VT_UI2:
+ if (readit) {
+ DWORD x;
+ hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
+ if (hres) ERR("Failed to read integer 4 byte\n");
+ memcpy(arg,&x,2);
+ }
+ if (debugout) TRACE_(olerelay)("%04lx",*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");
+ memcpy(arg,&x,1);
+ }
+ if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);
+ return hres;
+ case VT_I4|VT_BYREF:
+ hres = S_OK;
+ if (alloc)
+ *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
+ if (readit) {
+ hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD));
+ if (hres) ERR("Failed to read integer 4 byte\n");
+ }
+ if (debugout) TRACE_(olerelay)("&0x%lx",*(DWORD*)*arg);
+ return hres;
+ case VT_BSTR|VT_BYREF: {
+ BSTR **bstr = (BSTR **)arg;
+ WCHAR *str;
+ DWORD len;
+
+ if (readit) {
+ hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
+ if (hres) {
+ ERR("failed to read bstr klen\n");
+ return hres;
+ }
+ if (len == -1) {
+ *bstr = CoTaskMemAlloc(sizeof(BSTR *));
+ **bstr = NULL;
+ if (debugout) TRACE_(olerelay)("<bstr NULL>");
+ } else {
+ str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
+ hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
+ if (hres) {
+ ERR("Failed to read BSTR.\n");
+ return hres;
+ }
+ *bstr = CoTaskMemAlloc(sizeof(BSTR *));
+ **bstr = SysAllocStringLen(str,len);
+ if (debugout) TRACE_(olerelay)("%s",relaystr(str));
+ HeapFree(GetProcessHeap(),0,str);
+ }
+ } else {
+ *bstr = NULL;
+ }
+ return S_OK;
+ }
+ case VT_BSTR: {
+ WCHAR *str;
+ DWORD len;
+
+ if (readit) {
+ hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
+ if (hres) {
+ ERR("failed to read bstr klen\n");
+ return hres;
+ }
+ if (len == -1) {
+ *arg = 0;
+ if (debugout) TRACE_(olerelay)("<bstr NULL>");
+ } else {
+ str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
+ hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
+ if (hres) {
+ ERR("Failed to read BSTR.\n");
+ return hres;
+ }
+ *arg = (DWORD)SysAllocStringLen(str,len);
+ if (debugout) TRACE_(olerelay)("%s",relaystr(str));
+ HeapFree(GetProcessHeap(),0,str);
+ }
+ } else {
+ *arg = 0;
+ }
+ 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 %lx for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
+ return hres;
+ }
+ ITypeInfo_GetTypeAttr(tinfo2,&tattr);
+ switch (tattr->typekind) {
+ case TKIND_ENUM: /* confirmed */
+ case TKIND_RECORD: /* FIXME: mostly untested */
+ derefhere=TRUE;
+ break;
+ case TKIND_ALIAS: /* FIXME: untested */
+ 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_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));
+ }
+ 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 %lx 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 (alloc)
+ *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance);
+
+ if (debugout) TRACE_(olerelay)("{");
+ for (i=0;i<tattr->cVars;i++) {
+ VARDESC *vdesc;
+
+ hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
+ if (hres) {
+ ERR("Could not get vardesc of %d\n",i);
+ return hres;
+ }
+ hres = deserialize_param(
+ tinfo2,
+ readit,
+ debugout,
+ alloc,
+ &vdesc->elemdescVar.tdesc,
+ (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst),
+ buf
+ );
+ ITypeInfo2_ReleaseVarDesc(tinfo2, vdesc);
+ if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(",");
+ }
+ if (debugout) TRACE_(olerelay)("}");
+ break;
+ }
+ case TKIND_ALIAS:
+ return deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf);
+ 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)("%lx",*arg);
+ return hres;
+ default:
+ ERR("Unhandled typekind %d\n",tattr->typekind);
+ hres = E_FAIL;
+ break;
+ }
+ }
+ 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. */
+ 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;
+ for (i=0;i<arrsize;i++)
+ deserialize_param(
+ tinfo,
+ readit,
+ debugout,
+ alloc,
+ &adesc->tdescElem,
+ (DWORD*)((LPBYTE)(arg)+i*_xsize(&adesc->tdescElem)),
+ buf
+ );
+ return S_OK;
+ }
+ default:
+ ERR("No handler for VT type %d!\n",tdesc->vt);
+ return S_OK;
+ }
+ }
+}
+
+/* Searches function, also in inherited interfaces */
+static HRESULT
+_get_funcdesc(
+ ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc, BSTR *iname, BSTR *fname)
+{
+ int i = 0, j = 0;
+ HRESULT hres;
+
+ if (fname) *fname = NULL;
+ if (iname) *iname = NULL;
+
+ *tactual = tinfo;
+ ITypeInfo_AddRef(*tactual);
+
+ while (1) {
+ hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i, fdesc);
+
+ if (hres) {
+ ITypeInfo *tinfo2;
+ HREFTYPE href;
+ TYPEATTR *attr;
+
+ hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
+ if (hres) {
+ ERR("GetTypeAttr failed with %lx\n",hres);
+ return hres;
+ }
+ /* Not found, so look in inherited ifaces. */
+ for (j=0;j<attr->cImplTypes;j++) {
+ hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);
+ if (hres) {
+ ERR("Did not find a reftype for interface offset %d?\n",j);
+ break;
+ }
+ hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
+ if (hres) {
+ ERR("Did not find a typeinfo for reftype %ld?\n",href);
+ continue;
+ }
+ hres = _get_funcdesc(tinfo2,iMethod,tactual,fdesc,iname,fname);
+ ITypeInfo_Release(tinfo2);
+ if (!hres) return S_OK;
+ }
+ return hres;
+ }
+ if (((*fdesc)->oVft/4) == iMethod) {
+ if (fname)
+ ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL);
+ if (iname)
+ ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL);
+ return S_OK;
+ }
+ i++;
+ }
+}
+
+static DWORD
+xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
+{
+ DWORD *args = ((DWORD*)&tpinfo)+1, *xargs;
+ const FUNCDESC *fdesc;
+ HRESULT hres;
+ int i, relaydeb = TRACE_ON(olerelay);
+ 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);
+ if (hres) {
+ ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
+ ITypeInfo_Release(tinfo);
+ 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 (relaydeb) {
+ 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)("(");
+ }
+
+ if (iname) SysFreeString(iname);
+ if (fname) 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,sizeof(names)/sizeof(names[0]),&nrofnames))
+ nrofnames = 0;
+ if (nrofnames > sizeof(names)/sizeof(names[0]))
+ ERR("Need more names!\n");
+
+ xargs = args;
+ for (i=0;i<fdesc->cParams;i++) {
+ ELEMDESC *elem = fdesc->lprgelemdescParam+i;
+ if (relaydeb) {
+ 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 (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags) && (elem->tdesc.vt != VT_PTR)) {
+ xargs+=_argsize(elem->tdesc.vt);
+ if (relaydeb) TRACE_(olerelay)("[out]");
+ continue;
+ }
+ hres = serialize_param(
+ tinfo,
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
+ relaydeb,
+ FALSE,
+ &elem->tdesc,
+ xargs,
+ &buf
+ );
+
+ if (hres) {
+ ERR("Failed to serialize param, hres %lx\n",hres);
+ break;
+ }
+ xargs+=_argsize(elem->tdesc.vt);
+ }
+ if (relaydeb) 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, %lx\n",hres);
+ goto exit;
+ }
+ memcpy(msg.Buffer,buf.base,buf.curoff);
+ if (relaydeb) TRACE_(olerelay)("\n");
+ hres = IRpcChannelBuffer_SendReceive(chanbuf,&msg,&status);
+ if (hres) {
+ ERR("RpcChannelBuffer SendReceive failed, %lx\n",hres);
+ goto exit;
+ }
+
+ if (relaydeb) TRACE_(olerelay)(" status = %08lx (",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 = args;
+ status = S_OK;
+ for (i=0;i<fdesc->cParams;i++) {
+ ELEMDESC *elem = fdesc->lprgelemdescParam+i;
+
+ if (relaydeb) {
+ 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 (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {
+ xargs += _argsize(elem->tdesc.vt);
+ if (relaydeb) TRACE_(olerelay)("[in]");
+ continue;
+ }
+ hres = deserialize_param(
+ tinfo,
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
+ relaydeb,
+ FALSE,
+ &(elem->tdesc),
+ xargs,
+ &buf
+ );
+ if (hres) {
+ ERR("Failed to unmarshall param, hres %lx\n",hres);
+ status = hres;
+ break;
+ }
+ xargs += _argsize(elem->tdesc.vt);
+ }
+
+ hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));
+ if (hres != S_OK)
+ goto exit;
+ if (relaydeb) TRACE_(olerelay)(") = %08lx\n", remoteresult);
+
+ hres = remoteresult;
+
+exit:
+ HeapFree(GetProcessHeap(),0,buf.base);
+ IRpcChannelBuffer_Release(chanbuf);
+ ITypeInfo_Release(tinfo);
+ TRACE("-- 0x%08lx\n", hres);
+ return hres;
+}
+
+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;
+}
+
+ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)
+{
+ TMProxyImpl *proxy = (TMProxyImpl *)iface;
+
+ TRACE("\n");
+
+ if (proxy->outerunknown)
+ return IUnknown_AddRef(proxy->outerunknown);
+
+ return 2; /* FIXME */
+}
+
+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;
+ HRESULT hr;
+
+ TRACE("(%p)\n", pctinfo);
+
+ if (!This->dispatch)
+ {
+ hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch,
+ (LPVOID *)&This->dispatch);
+ }
+ if (This->dispatch)
+ hr = IDispatch_GetTypeInfoCount(This->dispatch, pctinfo);
+
+ return hr;
+}
+
+static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
+{
+ TMProxyImpl *This = (TMProxyImpl *)iface;
+ HRESULT hr = S_OK;
+
+ TRACE("(%d, %lx, %p)\n", iTInfo, lcid, ppTInfo);
+
+ if (!This->dispatch)
+ {
+ hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch,
+ (LPVOID *)&This->dispatch);
+ }
+ if (This->dispatch)
+ hr = IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo);
+
+ return hr;
+}
+
+static HRESULT WINAPI ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
+{
+ TMProxyImpl *This = (TMProxyImpl *)iface;
+ HRESULT hr;
+
+ TRACE("(%s, %p, %d, 0x%lx, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
+
+ if (!This->dispatch)
+ {
+ hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch,
+ (LPVOID *)&This->dispatch);
+ }
+ if (This->dispatch)
+ hr = IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames,
+ cNames, lcid, rgDispId);
+
+ return hr;
+}
+
+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;
+ HRESULT hr;
+
+ TRACE("(%ld, %s, 0x%lx, 0x%x, %p, %p, %p, %p)\n", dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+
+ if (!This->dispatch)
+ {
+ hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch,
+ (LPVOID *)&This->dispatch);
+ }
+ if (This->dispatch)
+ hr = IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid,
+ wFlags, pDispParams, pVarResult, pExcepInfo,
+ puArgErr);
+
+ return hr;
+}
+
+static HRESULT WINAPI
+PSFacBuf_CreateProxy(
+ LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
+ IRpcProxyBuffer **ppProxy, LPVOID *ppv)
+{
+ HRESULT hres;
+ ITypeInfo *tinfo;
+ int i, nroffuncs;
+ const FUNCDESC *fdesc;
+ TMProxyImpl *proxy;
+ TYPEATTR *typeattr;
+
+ 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;
+ }
+ nroffuncs = _nroffuncs(tinfo);
+ proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));
+ if (!proxy) return E_OUTOFMEMORY;
+
+ assert(sizeof(TMAsmProxy) == 12);
+
+ proxy->dispatch = 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;
+ }
+
+ InitializeCriticalSection(&proxy->crit);
+
+ proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
+ for (i=0;i<nroffuncs;i++) {
+ TMAsmProxy *xasm = proxy->asmstubs+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;
+ default: {
+ int j;
+ /* nrofargs without This */
+ int nrofargs;
+ ITypeInfo *tinfo2;
+ hres = _get_funcdesc(tinfo,i,&tinfo2,&fdesc,NULL,NULL);
+ ITypeInfo_Release(tinfo2);
+ if (hres) {
+ ERR("GetFuncDesc %lx should not fail here.\n",hres);
+ return hres;
+ }
+ /* some args take more than 4 byte on the stack */
+ nrofargs = 0;
+ for (j=0;j<fdesc->cParams;j++)
+ nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);
+
+#ifdef __i386__
+ if (fdesc->callconv != CC_STDCALL) {
+ ERR("calling convention is not stdcall????\n");
+ return E_FAIL;
+ }
+/* popl %eax - return ptr
+ * pushl <nr>
+ * pushl %eax
+ * call xCall
+ * lret <nr> (+4)
+ *
+ *
+ * arg3 arg2 arg1 <method> <returnptr>
+ */
+ xasm->popleax = 0x58;
+ xasm->pushlval = 0x6a;
+ xasm->nr = i;
+ xasm->pushleax = 0x50;
+ xasm->lcall = 0xe8; /* relative jump */
+ xasm->xcall = (DWORD)xCall;
+ xasm->xcall -= (DWORD)&(xasm->lret);
+ xasm->lret = 0xc2;
+ xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
+ proxy->lpvtbl[i] = xasm;
+ break;
+#else
+ FIXME("not implemented on non i386\n");
+ return E_FAIL;
+#endif
+ }
+ }
+ }
+
+ /* 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)
+ {
+ proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount;
+ proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo;
+ proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames;
+ proxy->lpvtbl[6] = ProxyIDispatch_Invoke;
+ }
+ ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
+ }
+
+ proxy->lpvtbl2 = &tmproxyvtable;
+ /* one reference for the proxy */
+ proxy->ref = 1;
+ proxy->tinfo = tinfo;
+ memcpy(&proxy->iid,riid,sizeof(*riid));
+ proxy->chanbuf = 0;
+ *ppv = (LPVOID)proxy;
+ *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
+ IUnknown_AddRef((IUnknown *)*ppv);
+ return S_OK;
+}
+
+typedef struct _TMStubImpl {
+ const IRpcStubBufferVtbl *lpvtbl;
+ LONG ref;
+
+ LPUNKNOWN pUnk;
+ ITypeInfo *tinfo;
+ IID iid;
+} TMStubImpl;
+
+static HRESULT WINAPI
+TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv)
+{
+ if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
+ *ppv = (LPVOID)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 = (TMStubImpl *)iface;
+ ULONG refCount = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1);
+
+ return refCount;
+}
+
+static ULONG WINAPI
+TMStubImpl_Release(LPRPCSTUBBUFFER iface)
+{
+ TMStubImpl *This = (TMStubImpl *)iface;
+ ULONG refCount = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1);
+
+ if (!refCount)
+ {
+ IRpcStubBuffer_Disconnect(iface);
+ ITypeInfo_Release(This->tinfo);
+ CoTaskMemFree(This);
+ }
+ return refCount;
+}
+
+static HRESULT WINAPI
+TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer)
+{
+ TMStubImpl *This = (TMStubImpl *)iface;
+
+ TRACE("(%p)->(%p)\n", This, pUnkServer);
+
+ IUnknown_AddRef(pUnkServer);
+ This->pUnk = pUnkServer;
+ return S_OK;
+}
+
+static void WINAPI
+TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)
+{
+ TMStubImpl *This = (TMStubImpl *)iface;
+
+ TRACE("(%p)->()\n", This);
+
+ if (This->pUnk)
+ {
+ IUnknown_Release(This->pUnk);
+ This->pUnk = NULL;
+ }
+}
+
+static HRESULT WINAPI
+TMStubImpl_Invoke(
+ LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf)
+{
+ int i;
+ const FUNCDESC *fdesc;
+ TMStubImpl *This = (TMStubImpl *)iface;
+ HRESULT hres;
+ DWORD *args, res, *xargs, nrofargs;
+ marshal_state buf;
+ UINT nrofnames;
+ BSTR names[10];
+ BSTR iname = NULL;
+ ITypeInfo *tinfo;
+
+ 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;
+
+ TRACE("...\n");
+
+ if (xmsg->iMethod < 3) {
+ ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n");
+ return E_UNEXPECTED;
+ }
+
+ hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL);
+ if (hres) {
+ ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);
+ return hres;
+ }
+
+ if (iname && !lstrcmpW(iname, IDispatchW))
+ {
+ ERR("IDispatch cannot be marshaled by the typelib marshaler\n");
+ ITypeInfo_Release(tinfo);
+ return E_UNEXPECTED;
+ }
+
+ if (iname) SysFreeString (iname);
+
+ /* Need them for hack below */
+ memset(names,0,sizeof(names));
+ ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
+ if (nrofnames > sizeof(names)/sizeof(names[0])) {
+ ERR("Need more names!\n");
+ }
+
+ /*dump_FUNCDESC(fdesc);*/
+ nrofargs = 0;
+ for (i=0;i<fdesc->cParams;i++)
+ nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);
+ args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
+ if (!args) return E_OUTOFMEMORY;
+
+ /* 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,
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
+ FALSE,
+ TRUE,
+ &(elem->tdesc),
+ xargs,
+ &buf
+ );
+ xargs += _argsize(elem->tdesc.vt);
+ if (hres) {
+ ERR("Failed to deserialize param %s, hres %lx\n",relaystr(names[i+1]),hres);
+ break;
+ }
+ }
+
+ args[0] = (DWORD)This->pUnk;
+ res = _invoke(
+ (*((FARPROC**)args[0]))[fdesc->oVft/4],
+ fdesc->callconv,
+ (xargs-args),
+ args
+ );
+ buf.curoff = 0;
+
+ xargs = args+1;
+ for (i=0;i<fdesc->cParams;i++) {
+ ELEMDESC *elem = fdesc->lprgelemdescParam+i;
+ hres = serialize_param(
+ tinfo,
+ elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
+ FALSE,
+ TRUE,
+ &elem->tdesc,
+ xargs,
+ &buf
+ );
+ xargs += _argsize(elem->tdesc.vt);
+ if (hres) {
+ ERR("Failed to stuballoc param, hres %lx\n",hres);
+ break;
+ }
+ }
+
+ hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));
+ if (hres != S_OK)
+ return hres;
+
+ ITypeInfo_Release(tinfo);
+ HeapFree(GetProcessHeap(), 0, args);
+
+ xmsg->cbBuffer = buf.curoff;
+ if (rpcchanbuf)
+ {
+ hres = IRpcChannelBuffer_GetBuffer(rpcchanbuf, xmsg, &This->iid);
+ if (hres != S_OK)
+ ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08lx\n", hres);
+ }
+ else
+ {
+ /* FIXME: remove this case when we start sending an IRpcChannelBuffer
+ * object with builtin OLE */
+ RPC_STATUS status = I_RpcGetBuffer((RPC_MESSAGE *)xmsg);
+ if (status != RPC_S_OK)
+ {
+ ERR("I_RpcGetBuffer failed with error %ld\n", status);
+ hres = E_FAIL;
+ }
+ }
+
+ if (hres == S_OK)
+ memcpy(xmsg->Buffer, buf.base, buf.curoff);
+
+ HeapFree(GetProcessHeap(), 0, buf.base);
+
+ TRACE("returning\n");
+ return hres;
+}
+
+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 = (TMStubImpl *)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;
+
+ 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;
+ }
+ stub = CoTaskMemAlloc(sizeof(TMStubImpl));
+ if (!stub)
+ return E_OUTOFMEMORY;
+ stub->lpvtbl = &tmstubvtbl;
+ stub->ref = 1;
+ stub->tinfo = tinfo;
+ memcpy(&(stub->iid),riid,sizeof(*riid));
+ hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
+ *ppStub = (LPRPCSTUBBUFFER)stub;
+ TRACE("IRpcStubBuffer: %p\n", stub);
+ if (hres)
+ ERR("Connect to pUnkServer failed?\n");
+ return hres;
+}
+
+static const IPSFactoryBufferVtbl psfacbufvtbl = {
+ PSFacBuf_QueryInterface,
+ PSFacBuf_AddRef,
+ PSFacBuf_Release,
+ PSFacBuf_CreateProxy,
+ PSFacBuf_CreateStub
+};
+
+/* This is the whole PSFactoryBuffer object, just the vtableptr */
+static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
+
+/***********************************************************************
+ * TMARSHAL_DllGetClassObject
+ */
+HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
+{
+ if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
+ *ppv = &lppsfac;
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}