4 * Copyright 2002 Marcus Meissner
6 * The olerelay debug channel allows you to see calls marshalled by
7 * the typelib marshaller. It is not a generic COM relaying system.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #define NONAMELESSUNION
34 #define NONAMELESSSTRUCT
43 #include "wine/unicode.h"
46 #include "wine/debug.h"
49 static const WCHAR riidW[5] = {'r','i','i','d',0};
50 static const WCHAR pdispparamsW[] = {'p','d','i','s','p','p','a','r','a','m','s',0};
51 static const WCHAR ppvObjectW[] = {'p','p','v','O','b','j','e','c','t',0};
53 WINE_DEFAULT_DEBUG_CHANNEL(ole);
54 WINE_DECLARE_DEBUG_CHANNEL(olerelay);
56 #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
58 typedef struct _marshal_state {
64 IID iid; /* HACK: for VT_VOID */
67 /* used in the olerelay code to avoid having the L"" stuff added by debugstr_w */
68 static char *relaystr(WCHAR *in) {
69 char *tmp = (char *)debugstr_w(in);
71 tmp[strlen(tmp)-1] = '\0';
76 xbuf_add(marshal_state *buf, LPBYTE stuff, DWORD size) {
77 while (buf->size - buf->curoff < size) {
80 buf->base = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,buf->base,buf->size);
84 buf->base = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,32);
90 memcpy(buf->base+buf->curoff,stuff,size);
96 xbuf_get(marshal_state *buf, LPBYTE stuff, DWORD size) {
97 if (buf->size < buf->curoff+size) return E_FAIL;
98 memcpy(stuff,buf->base+buf->curoff,size);
104 xbuf_skip(marshal_state *buf, DWORD size) {
105 if (buf->size < buf->curoff+size) return E_FAIL;
111 _unmarshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN *pUnk) {
113 ULARGE_INTEGER newpos;
114 LARGE_INTEGER seekto;
119 TRACE("...%s...\n",debugstr_guid(riid));
121 hres = xbuf_get(buf,(LPBYTE)&xsize,sizeof(xsize));
122 if (hres) return hres;
123 if (xsize == 0) return S_OK;
124 hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
126 FIXME("Stream create failed %lx\n",hres);
129 hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res);
130 if (hres) { FIXME("stream write %lx\n",hres); return hres; }
131 memset(&seekto,0,sizeof(seekto));
132 hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
133 if (hres) { FIXME("Failed Seek %lx\n",hres); return hres;}
134 hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk);
136 FIXME("Marshalling interface %s failed with %lx\n",debugstr_guid(riid),hres);
139 IStream_Release(pStm);
140 return xbuf_skip(buf,xsize);
144 _marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) {
149 ULARGE_INTEGER newpos;
150 LARGE_INTEGER seekto;
159 TRACE("...%s...\n",debugstr_guid(riid));
160 hres=IUnknown_QueryInterface(pUnk,riid,(LPVOID*)&newiface);
162 TRACE("%p does not support iface %s\n",pUnk,debugstr_guid(riid));
165 hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
167 FIXME("Stream create failed %lx\n",hres);
170 hres = CoMarshalInterface(pStm,riid,newiface,0,NULL,0);
171 IUnknown_Release(newiface);
173 FIXME("Marshalling interface %s failed with %lx\n",
174 debugstr_guid(riid),hres
178 hres = IStream_Stat(pStm,&ststg,0);
179 tempbuf = HeapAlloc(GetProcessHeap(), 0, ststg.cbSize.u.LowPart);
180 memset(&seekto,0,sizeof(seekto));
181 hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
182 if (hres) { FIXME("Failed Seek %lx\n",hres); goto fail;}
183 hres = IStream_Read(pStm,tempbuf,ststg.cbSize.u.LowPart,&res);
184 if (hres) { FIXME("Failed Read %lx\n",hres); goto fail;}
185 IStream_Release(pStm);
186 xsize = ststg.cbSize.u.LowPart;
187 xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
188 hres = xbuf_add(buf,tempbuf,ststg.cbSize.u.LowPart);
189 HeapFree(GetProcessHeap(),0,tempbuf);
193 xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
197 /********************* OLE Proxy/Stub Factory ********************************/
198 static HRESULT WINAPI
199 PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) {
200 if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) {
201 *ppv = (LPVOID)iface;
202 /* No ref counting, static class */
205 FIXME("(%s) unknown IID?\n",debugstr_guid(iid));
206 return E_NOINTERFACE;
209 static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; }
210 static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; }
213 _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
216 char tlguid[200],typelibkey[300],interfacekey[300],ver[100];
219 DWORD tlguidlen, verlen, type, tlfnlen;
222 sprintf( interfacekey, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
223 riid->Data1, riid->Data2, riid->Data3,
224 riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
225 riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]
228 if (RegOpenKeyA(HKEY_CLASSES_ROOT,interfacekey,&ikey)) {
229 FIXME("No %s key found.\n",interfacekey);
233 tlguidlen = sizeof(tlguid);
234 if (RegQueryValueExA(ikey,NULL,NULL,&type,tlguid,&tlguidlen)) {
235 FIXME("Getting typelib guid failed.\n");
240 verlen = sizeof(ver);
241 if (RegQueryValueExA(ikey,"Version",NULL,&type,ver,&verlen)) {
242 FIXME("Could not get version value?\n");
247 sprintf(typelibkey,"Typelib\\%s\\%s\\0\\win32",tlguid,ver);
248 tlfnlen = sizeof(tlfn);
249 if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) {
250 FIXME("Could not get typelib fn?\n");
253 MultiByteToWideChar(CP_ACP, 0, tlfn, -1, tlfnW, -1);
254 hres = LoadTypeLib(tlfnW,&tl);
256 ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid));
259 hres = ITypeLib_GetTypeInfoOfGuid(tl,riid,ti);
261 ERR("typelib does not contain info for %s?\n",debugstr_guid(riid));
262 ITypeLib_Release(tl);
265 /* FIXME: do this? ITypeLib_Release(tl); */
269 /* Determine nr of functions. Since we use the toplevel interface and all
270 * inherited ones have lower numbers, we are ok to not to descent into
271 * the inheritance tree I think.
273 static int _nroffuncs(ITypeInfo *tinfo) {
280 hres = ITypeInfo_GetFuncDesc(tinfo,n,&fdesc);
283 if (fdesc->oVft/4 > max)
292 #include "pshpack1.h"
294 typedef struct _TMAsmProxy {
308 # error You need to implement stubless proxies for your architecture
311 typedef struct _TMProxyImpl {
313 IRpcProxyBufferVtbl *lpvtbl2;
316 TMAsmProxy *asmstubs;
318 IRpcChannelBuffer* chanbuf;
320 CRITICAL_SECTION crit;
323 static HRESULT WINAPI
324 TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv)
327 if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) {
328 *ppv = (LPVOID)iface;
329 IRpcProxyBuffer_AddRef(iface);
332 FIXME("no interface for %s\n",debugstr_guid(riid));
333 return E_NOINTERFACE;
337 TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface)
339 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
343 return InterlockedIncrement(&This->ref);
347 TMProxyImpl_Release(LPRPCPROXYBUFFER iface)
350 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
354 refs = InterlockedDecrement(&This->ref);
357 DeleteCriticalSection(&This->crit);
358 if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf);
359 VirtualFree(This->asmstubs, 0, MEM_RELEASE);
365 static HRESULT WINAPI
367 LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer)
369 ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
371 TRACE("(%p)\n", pRpcChannelBuffer);
373 EnterCriticalSection(&This->crit);
375 IRpcChannelBuffer_AddRef(pRpcChannelBuffer);
376 This->chanbuf = pRpcChannelBuffer;
378 LeaveCriticalSection(&This->crit);
384 TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface)
386 ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
390 EnterCriticalSection(&This->crit);
392 IRpcChannelBuffer_Release(This->chanbuf);
393 This->chanbuf = NULL;
395 LeaveCriticalSection(&This->crit);
399 static IRpcProxyBufferVtbl tmproxyvtable = {
400 TMProxyImpl_QueryInterface,
404 TMProxyImpl_Disconnect
407 /* how much space do we use on stack in DWORD steps. */
412 return sizeof(DATE)/sizeof(DWORD);
414 return (sizeof(VARIANT)+3)/sizeof(DWORD);
421 _xsize(TYPEDESC *td) {
426 return sizeof(VARIANT)+3;
429 ARRAYDESC *adesc = td->u.lpadesc;
431 for (i=0;i<adesc->cDims;i++)
432 arrsize *= adesc->rgbounds[i].cElements;
433 return arrsize*_xsize(&adesc->tdescElem);
458 TRACE("(tdesc.vt %d)\n",tdesc->vt);
461 case VT_EMPTY: /* nothing. empty variant for instance */
472 if (debugout) TRACE_(olerelay)("%lx",*arg);
474 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
478 VARIANT *vt = (VARIANT*)arg;
479 DWORD vttype = V_VT(vt);
481 if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype);
484 hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
485 if (hres) return hres;
487 /* need to recurse since we need to free the stuff */
488 hres = serialize_param(tinfo,writeit,debugout,dealloc,&tdesc2,&(V_I4(vt)),buf);
489 if (debugout) TRACE_(olerelay)(")");
495 TRACE_(olerelay)("%s",relaystr((BSTR)*arg));
497 TRACE_(olerelay)("<bstr NULL>");
502 hres = xbuf_add(buf,(LPBYTE)&fakelen,4);
506 DWORD *bstr = ((DWORD*)(*arg))-1;
508 hres = xbuf_add(buf,(LPBYTE)bstr,bstr[0]+4);
515 SysFreeString((BSTR)*arg);
521 if (debugout) TRACE_(olerelay)("*");
523 cookie = *arg ? 0x42424242 : 0;
524 hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));
529 if (debugout) TRACE_(olerelay)("NULL");
532 hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf);
533 if (dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)arg);
537 if (debugout) TRACE_(olerelay)("unk(0x%lx)",*arg);
539 hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg);
542 if (debugout) TRACE_(olerelay)("idisp(0x%lx)",*arg);
544 hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg);
547 if (debugout) TRACE_(olerelay)("<void>");
549 case VT_USERDEFINED: {
553 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
555 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
558 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
559 switch (tattr->typekind) {
561 case TKIND_INTERFACE:
563 hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg);
567 if (debugout) TRACE_(olerelay)("{");
568 for (i=0;i<tattr->cVars;i++) {
573 hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
575 FIXME("Could not get vardesc of %d\n",i);
578 /* Need them for hack below */
580 memset(names,0,sizeof(names));
581 hres = ITypeInfo_GetNames(tinfo2,vdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
582 if (nrofnames > sizeof(names)/sizeof(names[0])) {
583 ERR("Need more names!\n");
585 if (!hres && debugout)
586 TRACE_(olerelay)("%s=",relaystr(names[0]));
588 elem2 = &vdesc->elemdescVar;
589 tdesc2 = &elem2->tdesc;
590 hres = serialize_param(
596 (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst),
601 if (debugout && (i<(tattr->cVars-1)))
602 TRACE_(olerelay)(",");
604 if (buf->thisisiid && (tattr->cbSizeInstance==sizeof(GUID)))
605 memcpy(&(buf->iid),arg,sizeof(buf->iid));
606 if (debugout) TRACE_(olerelay)("}");
610 FIXME("Unhandled typekind %d\n",tattr->typekind);
614 ITypeInfo_Release(tinfo2);
618 ARRAYDESC *adesc = tdesc->u.lpadesc;
621 if (debugout) TRACE_(olerelay)("carr");
622 for (i=0;i<adesc->cDims;i++) {
623 if (debugout) TRACE_(olerelay)("[%ld]",adesc->rgbounds[i].cElements);
624 arrsize *= adesc->rgbounds[i].cElements;
626 if (debugout) TRACE_(olerelay)("[");
627 for (i=0;i<arrsize;i++) {
628 hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);
631 if (debugout && (i<arrsize-1)) TRACE_(olerelay)(",");
633 if (debugout) TRACE_(olerelay)("]");
637 ERR("Unhandled marshal type %d.\n",tdesc->vt);
643 serialize_LPVOID_ptr(
655 if ((tdesc->vt != VT_PTR) ||
656 (tdesc->u.lptdesc->vt != VT_PTR) ||
657 (tdesc->u.lptdesc->u.lptdesc->vt != VT_VOID)
659 FIXME("ppvObject not expressed as VT_PTR -> VT_PTR -> VT_VOID?\n");
662 cookie = (*arg) ? 0x42424242: 0x0;
664 hres = xbuf_add(buf, (LPVOID)&cookie, sizeof(cookie));
669 if (debugout) TRACE_(olerelay)("<lpvoid NULL>");
673 TRACE_(olerelay)("ppv(%p)",*(LPUNKNOWN*)*arg);
675 hres = _marshal_interface(buf,&(buf->iid),*(LPUNKNOWN*)*arg);
680 HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
685 serialize_DISPPARAM_ptr(
699 if ((tdesc->vt != VT_PTR) || (tdesc->u.lptdesc->vt != VT_USERDEFINED)) {
700 FIXME("DISPPARAMS not expressed as VT_PTR -> VT_USERDEFINED?\n");
704 cookie = *arg ? 0x42424242 : 0x0;
706 hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));
711 if (debugout) TRACE_(olerelay)("<DISPPARAMS NULL>");
714 disp = (DISPPARAMS*)*arg;
716 hres = xbuf_add(buf,(LPBYTE)&disp->cArgs,sizeof(disp->cArgs));
720 if (debugout) TRACE_(olerelay)("D{");
721 for (i=0;i<disp->cArgs;i++) {
724 vtdesc.vt = VT_VARIANT;
731 (DWORD*)(disp->rgvarg+i),
734 if (debugout && (i<disp->cArgs-1))
735 TRACE_(olerelay)(",");
738 HeapFree(GetProcessHeap(),0,disp->rgvarg);
740 hres = xbuf_add(buf,(LPBYTE)&disp->cNamedArgs,sizeof(disp->cNamedArgs));
744 if (debugout) TRACE_(olerelay)("}{");
745 for (i=0;i<disp->cNamedArgs;i++) {
755 (DWORD*)(disp->rgdispidNamedArgs+i),
758 if (debugout && (i<disp->cNamedArgs-1))
759 TRACE_(olerelay)(",");
761 if (debugout) TRACE_(olerelay)("}");
763 HeapFree(GetProcessHeap(),0,disp->rgdispidNamedArgs);
764 HeapFree(GetProcessHeap(),0,disp);
781 TRACE("vt %d at %p\n",tdesc->vt,arg);
786 if (debugout) TRACE_(olerelay)("<empty>");
789 if (debugout) TRACE_(olerelay)("<null>");
792 VARIANT *vt = (VARIANT*)arg;
797 hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype));
799 FIXME("vt type not read?\n");
802 memset(&tdesc2,0,sizeof(tdesc2));
805 if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype);
806 hres = deserialize_param(tinfo, readit, debugout, alloc, &tdesc2, &(V_I4(vt)), buf);
807 TRACE_(olerelay)(")");
815 case VT_BOOL: case VT_I4: case VT_UI4: case VT_UINT: case VT_R4:
819 hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
820 if (hres) FIXME("Failed to read integer 4 byte\n");
822 if (debugout) TRACE_(olerelay)("%lx",*arg);
829 hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
831 FIXME("failed to read bstr klen\n");
836 if (debugout) TRACE_(olerelay)("<bstr NULL>");
838 str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR));
839 hres = xbuf_get(buf,(LPBYTE)str,len);
841 FIXME("Failed to read BSTR.\n");
844 *arg = (DWORD)SysAllocStringLen(str,len);
845 if (debugout) TRACE_(olerelay)("%s",relaystr(str));
846 HeapFree(GetProcessHeap(),0,str);
857 derefhere = (tdesc->u.lptdesc->vt != VT_USERDEFINED);
860 hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));
862 FIXME("Failed to load pointer cookie.\n");
865 if (cookie != 0x42424242) {
866 if (debugout) TRACE_(olerelay)("NULL");
870 if (debugout) TRACE_(olerelay)("*");
874 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc));
877 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, (LPDWORD)*arg, buf);
879 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, arg, buf);
882 /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */
884 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
887 hres = _unmarshal_interface(buf,&IID_IUnknown,(LPUNKNOWN*)arg);
889 TRACE_(olerelay)("unk(%p)",arg);
894 hres = _unmarshal_interface(buf,&IID_IDispatch,(LPUNKNOWN*)arg);
896 TRACE_(olerelay)("idisp(%p)",arg);
899 if (debugout) TRACE_(olerelay)("<void>");
901 case VT_USERDEFINED: {
905 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
907 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
910 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
912 FIXME("Could not get typeattr in VT_USERDEFINED.\n");
915 *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,tattr->cbSizeInstance);
916 switch (tattr->typekind) {
918 case TKIND_INTERFACE:
920 hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);
925 if (debugout) TRACE_(olerelay)("{");
926 for (i=0;i<tattr->cVars;i++) {
929 hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
931 FIXME("Could not get vardesc of %d\n",i);
934 hres = deserialize_param(
939 &vdesc->elemdescVar.tdesc,
940 (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst),
943 if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(",");
945 if (buf->thisisiid && (tattr->cbSizeInstance==sizeof(GUID)))
946 memcpy(&(buf->iid),(LPBYTE)*arg,sizeof(buf->iid));
947 if (debugout) TRACE_(olerelay)("}");
951 ERR("Unhandled typekind %d\n",tattr->typekind);
957 FIXME("failed to stuballoc in TKIND_RECORD.\n");
958 ITypeInfo_Release(tinfo2);
962 /* arg is pointing to the start of the array. */
963 ARRAYDESC *adesc = tdesc->u.lpadesc;
966 if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n");
967 for (i=0;i<adesc->cDims;i++)
968 arrsize *= adesc->rgbounds[i].cElements;
969 for (i=0;i<arrsize;i++)
976 (DWORD*)((LPBYTE)(arg)+i*_xsize(&adesc->tdescElem)),
982 ERR("No handler for VT type %d!\n",tdesc->vt);
989 deserialize_LPVOID_ptr(
1001 if ((tdesc->vt != VT_PTR) ||
1002 (tdesc->u.lptdesc->vt != VT_PTR) ||
1003 (tdesc->u.lptdesc->u.lptdesc->vt != VT_VOID)
1005 FIXME("ppvObject not expressed as VT_PTR -> VT_PTR -> VT_VOID?\n");
1009 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPVOID));
1011 hres = xbuf_get(buf, (LPVOID)&cookie, sizeof(cookie));
1014 if (cookie != 0x42424242) {
1016 if (debugout) TRACE_(olerelay)("<lpvoid NULL>");
1021 hres = _unmarshal_interface(buf,&buf->iid,(LPUNKNOWN*)*arg);
1025 if (debugout) TRACE_(olerelay)("ppv(%p)",(LPVOID)*arg);
1030 deserialize_DISPPARAM_ptr(
1044 if ((tdesc->vt != VT_PTR) || (tdesc->u.lptdesc->vt != VT_USERDEFINED)) {
1045 FIXME("DISPPARAMS not expressed as VT_PTR -> VT_USERDEFINED?\n");
1049 hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));
1054 if (debugout) TRACE_(olerelay)("<DISPPARAMS NULL>");
1059 *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPPARAMS));
1060 disps = (DISPPARAMS*)*arg;
1063 hres = xbuf_get(buf, (LPBYTE)&disps->cArgs, sizeof(disps->cArgs));
1067 disps->rgvarg = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(VARIANT)*disps->cArgs);
1068 if (debugout) TRACE_(olerelay)("D{");
1069 for (i=0; i< disps->cArgs; i++) {
1072 vdesc.vt = VT_VARIANT;
1073 hres = deserialize_param(
1079 (DWORD*)(disps->rgvarg+i),
1083 if (debugout) TRACE_(olerelay)("}{");
1084 hres = xbuf_get(buf, (LPBYTE)&disps->cNamedArgs, sizeof(disps->cNamedArgs));
1087 if (disps->cNamedArgs) {
1089 disps->rgdispidNamedArgs = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPID)*disps->cNamedArgs);
1090 for (i=0; i< disps->cNamedArgs; i++) {
1094 hres = deserialize_param(
1100 (DWORD*)(disps->rgdispidNamedArgs+i),
1103 if (debugout && i<(disps->cNamedArgs-1)) TRACE_(olerelay)(",");
1106 if (debugout) TRACE_(olerelay)("}");
1110 /* Searches function, also in inherited interfaces */
1113 ITypeInfo *tinfo, int iMethod, FUNCDESC **fdesc, BSTR *iname, BSTR *fname)
1118 if (fname) *fname = NULL;
1119 if (iname) *iname = NULL;
1122 hres = ITypeInfo_GetFuncDesc(tinfo, i, fdesc);
1128 hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
1130 FIXME("GetTypeAttr failed with %lx\n",hres);
1133 /* Not found, so look in inherited ifaces. */
1134 for (j=0;j<attr->cImplTypes;j++) {
1135 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);
1137 FIXME("Did not find a reftype for interface offset %d?\n",j);
1140 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
1142 FIXME("Did not find a typeinfo for reftype %ld?\n",href);
1145 hres = _get_funcdesc(tinfo2,iMethod,fdesc,iname,fname);
1146 ITypeInfo_Release(tinfo2);
1147 if (!hres) return S_OK;
1151 if (((*fdesc)->oVft/4) == iMethod) {
1153 ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL);
1155 ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL);
1164 xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
1166 DWORD *args = ((DWORD*)&tpinfo)+1, *xargs;
1169 int i, relaydeb = TRACE_ON(olerelay);
1177 EnterCriticalSection(&tpinfo->crit);
1179 hres = _get_funcdesc(tpinfo->tinfo,method,&fdesc,&iname,&fname);
1181 ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
1182 LeaveCriticalSection(&tpinfo->crit);
1187 TRACE_(olerelay)("->");
1189 TRACE_(olerelay)("%s:",relaystr(iname));
1191 TRACE_(olerelay)("%s(%d)",relaystr(fname),method);
1193 TRACE_(olerelay)("%d",method);
1194 TRACE_(olerelay)("(");
1195 if (iname) SysFreeString(iname);
1196 if (fname) SysFreeString(fname);
1198 /* Need them for hack below */
1199 memset(names,0,sizeof(names));
1200 if (ITypeInfo_GetNames(tpinfo->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
1202 if (nrofnames > sizeof(names)/sizeof(names[0]))
1203 ERR("Need more names!\n");
1205 memset(&buf,0,sizeof(buf));
1206 buf.iid = IID_IUnknown;
1208 xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));
1209 if (relaydeb) TRACE_(olerelay)("riid=%s,[out]",debugstr_guid((REFIID)args[0]));
1212 for (i=0;i<fdesc->cParams;i++) {
1213 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
1214 BOOL isserialized = FALSE;
1216 if (i) TRACE_(olerelay)(",");
1217 if (i+1<nrofnames && names[i+1])
1218 TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1220 /* No need to marshal other data than FIN */
1221 if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN)) {
1222 xargs+=_argsize(elem->tdesc.vt);
1223 if (relaydeb) TRACE_(olerelay)("[out]");
1226 if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
1227 /* If the parameter is 'riid', we use it as interface IID
1228 * for a later ppvObject serialization.
1230 buf.thisisiid = !lstrcmpW(names[i+1],riidW);
1232 /* DISPPARAMS* needs special serializer */
1233 if (!lstrcmpW(names[i+1],pdispparamsW)) {
1234 hres = serialize_DISPPARAM_ptr(
1236 elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
1243 isserialized = TRUE;
1245 if (!lstrcmpW(names[i+1],ppvObjectW)) {
1246 hres = serialize_LPVOID_ptr(
1248 elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
1256 isserialized = TRUE;
1260 hres = serialize_param(
1262 elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
1271 FIXME("Failed to serialize param, hres %lx\n",hres);
1274 xargs+=_argsize(elem->tdesc.vt);
1277 if (relaydeb) TRACE_(olerelay)(")");
1278 memset(&msg,0,sizeof(msg));
1279 msg.cbBuffer = buf.curoff;
1280 msg.iMethod = method;
1281 hres = IRpcChannelBuffer_GetBuffer(tpinfo->chanbuf,&msg,&(tpinfo->iid));
1283 FIXME("RpcChannelBuffer GetBuffer failed, %lx\n",hres);
1284 LeaveCriticalSection(&tpinfo->crit);
1287 memcpy(msg.Buffer,buf.base,buf.curoff);
1288 if (relaydeb) TRACE_(olerelay)("\n");
1289 hres = IRpcChannelBuffer_SendReceive(tpinfo->chanbuf,&msg,&status);
1291 FIXME("RpcChannelBuffer SendReceive failed, %lx\n",hres);
1292 LeaveCriticalSection(&tpinfo->crit);
1296 if (relaydeb) TRACE_(olerelay)(" = %08lx (",status);
1298 buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);
1300 buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);
1301 buf.size = msg.cbBuffer;
1302 memcpy(buf.base,msg.Buffer,buf.size);
1305 _unmarshal_interface(&buf,(REFIID)args[0],(LPUNKNOWN*)args[1]);
1306 if (relaydeb) TRACE_(olerelay)("[in],%p",*((DWORD**)args[1]));
1309 for (i=0;i<fdesc->cParams;i++) {
1310 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
1311 BOOL isdeserialized = FALSE;
1314 if (i) TRACE_(olerelay)(",");
1315 if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1317 /* No need to marshal other data than FOUT I think */
1318 if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)) {
1319 xargs += _argsize(elem->tdesc.vt);
1320 if (relaydeb) TRACE_(olerelay)("[in]");
1323 if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
1324 /* If the parameter is 'riid', we use it as interface IID
1325 * for a later ppvObject serialization.
1327 buf.thisisiid = !lstrcmpW(names[i+1],riidW);
1329 /* deserialize DISPPARAM */
1330 if (!lstrcmpW(names[i+1],pdispparamsW)) {
1331 hres = deserialize_DISPPARAM_ptr(
1333 elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1341 FIXME("Failed to deserialize DISPPARAM*, hres %lx\n",hres);
1344 isdeserialized = TRUE;
1346 if (!lstrcmpW(names[i+1],ppvObjectW)) {
1347 hres = deserialize_LPVOID_ptr(
1349 elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1357 isdeserialized = TRUE;
1360 if (!isdeserialized)
1361 hres = deserialize_param(
1363 elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1371 FIXME("Failed to unmarshall param, hres %lx\n",hres);
1374 xargs += _argsize(elem->tdesc.vt);
1377 if (relaydeb) TRACE_(olerelay)(")\n");
1378 HeapFree(GetProcessHeap(),0,buf.base);
1380 LeaveCriticalSection(&tpinfo->crit);
1385 static HRESULT WINAPI
1386 PSFacBuf_CreateProxy(
1387 LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
1388 IRpcProxyBuffer **ppProxy, LPVOID *ppv)
1396 TRACE("(...%s...)\n",debugstr_guid(riid));
1397 hres = _get_typeinfo_for_iid(riid,&tinfo);
1399 FIXME("No typeinfo for %s?\n",debugstr_guid(riid));
1402 nroffuncs = _nroffuncs(tinfo);
1403 proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));
1404 if (!proxy) return E_OUTOFMEMORY;
1406 assert(sizeof(TMAsmProxy) == 12);
1408 proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
1409 if (!proxy->asmstubs) {
1410 ERR("Could not commit pages for proxy thunks\n");
1411 CoTaskMemFree(proxy);
1412 return E_OUTOFMEMORY;
1415 InitializeCriticalSection(&proxy->crit);
1417 proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
1418 for (i=0;i<nroffuncs;i++) {
1420 TMAsmProxy *xasm = proxy->asmstubs+i;
1422 /* nrofargs without This */
1424 case 0: nrofargs = 2;
1426 case 1: case 2: nrofargs = 0;
1430 hres = _get_funcdesc(tinfo,i,&fdesc,NULL,NULL);
1432 FIXME("GetFuncDesc %lx should not fail here.\n",hres);
1435 /* some args take more than 4 byte on the stack */
1437 for (j=0;j<fdesc->cParams;j++)
1438 nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);
1440 if (fdesc->callconv != CC_STDCALL) {
1441 ERR("calling convention is not stdcall????\n");
1447 /* popl %eax - return ptr
1454 * arg3 arg2 arg1 <method> <returnptr>
1456 xasm->popleax = 0x58;
1457 xasm->pushlval = 0x6a;
1459 xasm->pushleax = 0x50;
1460 xasm->lcall = 0xe8; /* relative jump */
1461 xasm->xcall = (DWORD)xCall;
1462 xasm->xcall -= (DWORD)&(xasm->lret);
1464 xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
1465 proxy->lpvtbl[i] = xasm;
1467 proxy->lpvtbl2 = &tmproxyvtable;
1468 /* 1 reference for the proxy and 1 for the object */
1470 proxy->tinfo = tinfo;
1471 memcpy(&proxy->iid,riid,sizeof(*riid));
1472 *ppv = (LPVOID)proxy;
1473 *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
1477 typedef struct _TMStubImpl {
1478 IRpcStubBufferVtbl *lpvtbl;
1486 static HRESULT WINAPI
1487 TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv)
1489 if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
1490 *ppv = (LPVOID)iface;
1491 IRpcStubBuffer_AddRef(iface);
1494 FIXME("%s, not supported IID.\n",debugstr_guid(riid));
1495 return E_NOINTERFACE;
1499 TMStubImpl_AddRef(LPRPCSTUBBUFFER iface)
1501 TMStubImpl *This = (TMStubImpl *)iface;
1503 TRACE("(%p) before %lu\n", This, This->ref);
1505 return InterlockedIncrement(&This->ref);
1509 TMStubImpl_Release(LPRPCSTUBBUFFER iface)
1512 TMStubImpl *This = (TMStubImpl *)iface;
1514 TRACE("(%p) after %lu\n", This, This->ref-1);
1516 refs = InterlockedDecrement(&This->ref);
1519 IRpcStubBuffer_Disconnect(iface);
1520 CoTaskMemFree(This);
1525 static HRESULT WINAPI
1526 TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer)
1528 TMStubImpl *This = (TMStubImpl *)iface;
1530 TRACE("(%p)->(%p)\n", This, pUnkServer);
1532 IUnknown_AddRef(pUnkServer);
1533 This->pUnk = pUnkServer;
1538 TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)
1540 TMStubImpl *This = (TMStubImpl *)iface;
1542 TRACE("(%p)->()\n", This);
1544 IUnknown_Release(This->pUnk);
1549 static HRESULT WINAPI
1551 LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf)
1555 TMStubImpl *This = (TMStubImpl *)iface;
1557 DWORD *args, res, *xargs, nrofargs;
1562 memset(&buf,0,sizeof(buf));
1563 buf.size = xmsg->cbBuffer;
1564 buf.base = xmsg->Buffer;
1566 buf.iid = IID_IUnknown;
1569 if (xmsg->iMethod == 0) { /* QI */
1571 /* in: IID, out: <iface> */
1573 xbuf_get(&buf,(LPBYTE)&xiid,sizeof(xiid));
1575 hres = _marshal_interface(&buf,&xiid,This->pUnk);
1576 xmsg->Buffer = buf.base; /* Might have been reallocated */
1577 xmsg->cbBuffer = buf.size;
1580 hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,NULL,NULL);
1582 FIXME("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);
1585 /* Need them for hack below */
1586 memset(names,0,sizeof(names));
1587 ITypeInfo_GetNames(This->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
1588 if (nrofnames > sizeof(names)/sizeof(names[0])) {
1589 ERR("Need more names!\n");
1592 /*dump_FUNCDESC(fdesc);*/
1594 for (i=0;i<fdesc->cParams;i++)
1595 nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);
1596 args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
1597 if (!args) return E_OUTOFMEMORY;
1599 /* Allocate all stuff used by call. */
1601 for (i=0;i<fdesc->cParams;i++) {
1602 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
1603 BOOL isdeserialized = FALSE;
1605 if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
1606 /* If the parameter is 'riid', we use it as interface IID
1607 * for a later ppvObject serialization.
1609 buf.thisisiid = !lstrcmpW(names[i+1],riidW);
1611 /* deserialize DISPPARAM */
1612 if (!lstrcmpW(names[i+1],pdispparamsW)) {
1613 hres = deserialize_DISPPARAM_ptr(
1615 elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
1623 FIXME("Failed to deserialize DISPPARAM*, hres %lx\n",hres);
1626 isdeserialized = TRUE;
1628 if (!lstrcmpW(names[i+1],ppvObjectW)) {
1629 hres = deserialize_LPVOID_ptr(
1631 elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1639 isdeserialized = TRUE;
1642 if (!isdeserialized)
1643 hres = deserialize_param(
1645 elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
1652 xargs += _argsize(elem->tdesc.vt);
1654 FIXME("Failed to deserialize param %s, hres %lx\n",relaystr(names[i+1]),hres);
1658 hres = IUnknown_QueryInterface(This->pUnk,&(This->iid),(LPVOID*)&(args[0]));
1660 ERR("Does not support iface %s\n",debugstr_guid(&(This->iid)));
1664 (*((FARPROC**)args[0]))[fdesc->oVft/4],
1669 IUnknown_Release((LPUNKNOWN)args[0]);
1672 for (i=0;i<fdesc->cParams;i++) {
1673 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
1674 BOOL isserialized = FALSE;
1676 if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
1677 /* If the parameter is 'riid', we use it as interface IID
1678 * for a later ppvObject serialization.
1680 buf.thisisiid = !lstrcmpW(names[i+1],riidW);
1682 /* DISPPARAMS* needs special serializer */
1683 if (!lstrcmpW(names[i+1],pdispparamsW)) {
1684 hres = serialize_DISPPARAM_ptr(
1686 elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1693 isserialized = TRUE;
1695 if (!lstrcmpW(names[i+1],ppvObjectW)) {
1696 hres = serialize_LPVOID_ptr(
1698 elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1706 isserialized = TRUE;
1710 hres = serialize_param(
1712 elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1719 xargs += _argsize(elem->tdesc.vt);
1721 FIXME("Failed to stuballoc param, hres %lx\n",hres);
1725 /* might need to use IRpcChannelBuffer_GetBuffer ? */
1726 xmsg->cbBuffer = buf.curoff;
1727 xmsg->Buffer = buf.base;
1728 HeapFree(GetProcessHeap(),0,args);
1732 static LPRPCSTUBBUFFER WINAPI
1733 TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {
1734 FIXME("Huh (%s)?\n",debugstr_guid(riid));
1739 TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {
1740 TMStubImpl *This = (TMStubImpl *)iface;
1742 return This->ref; /*FIXME? */
1745 static HRESULT WINAPI
1746 TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {
1751 TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
1755 IRpcStubBufferVtbl tmstubvtbl = {
1756 TMStubImpl_QueryInterface,
1760 TMStubImpl_Disconnect,
1762 TMStubImpl_IsIIDSupported,
1763 TMStubImpl_CountRefs,
1764 TMStubImpl_DebugServerQueryInterface,
1765 TMStubImpl_DebugServerRelease
1768 static HRESULT WINAPI
1769 PSFacBuf_CreateStub(
1770 LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
1771 IRpcStubBuffer** ppStub
1777 TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
1778 hres = _get_typeinfo_for_iid(riid,&tinfo);
1780 FIXME("No typeinfo for %s?\n",debugstr_guid(riid));
1783 stub = CoTaskMemAlloc(sizeof(TMStubImpl));
1785 return E_OUTOFMEMORY;
1786 stub->lpvtbl = &tmstubvtbl;
1788 stub->tinfo = tinfo;
1789 memcpy(&(stub->iid),riid,sizeof(*riid));
1790 hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
1791 *ppStub = (LPRPCSTUBBUFFER)stub;
1792 TRACE("IRpcStubBuffer: %p\n", stub);
1794 FIXME("Connect to pUnkServer failed?\n");
1798 static IPSFactoryBufferVtbl psfacbufvtbl = {
1799 PSFacBuf_QueryInterface,
1802 PSFacBuf_CreateProxy,
1806 /* This is the whole PSFactoryBuffer object, just the vtableptr */
1807 static IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
1809 /***********************************************************************
1810 * DllGetClassObject [OLE32.63]
1813 TypeLibFac_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
1815 if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
1819 return E_NOINTERFACE;