blob: 2dee9d7926285e40b9396d78f8fbe29232e1ce0d [file] [log] [blame]
Marcus Meissner0749fc22002-02-05 18:11:17 +00001/*
2 * TYPELIB Marshaler
3 *
Marcus Meissner41079862005-03-29 13:06:44 +00004 * Copyright 2002,2005 Marcus Meissner
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
Mike Hearnd440ca42004-06-17 23:03:26 +00006 * The olerelay debug channel allows you to see calls marshalled by
7 * the typelib marshaller. It is not a generic COM relaying system.
8 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00009 * 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.
13 *
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.
18 *
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
Jonathan Ernst360a3f92006-05-18 14:49:52 +020021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Marcus Meissner0749fc22002-02-05 18:11:17 +000022 */
23
24#include "config.h"
25
26#include <assert.h>
27#include <stdlib.h>
28#include <string.h>
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000029#include <stdarg.h>
Marcus Meissner0749fc22002-02-05 18:11:17 +000030#include <stdio.h>
31#include <ctype.h>
32
Francois Gouget486d0202004-10-07 03:06:48 +000033#define COBJMACROS
Dimitrie O. Paun297f3d82003-01-07 20:36:20 +000034#define NONAMELESSUNION
35#define NONAMELESSSTRUCT
Francois Gouget486d0202004-10-07 03:06:48 +000036
Marcus Meissner0749fc22002-02-05 18:11:17 +000037#include "winerror.h"
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000038#include "windef.h"
Alexandre Julliard864ca062003-08-20 18:22:31 +000039#include "winbase.h"
Marcus Meissner0749fc22002-02-05 18:11:17 +000040#include "winnls.h"
41#include "winreg.h"
42#include "winuser.h"
43
44#include "ole2.h"
Huw Davies86d94572006-05-10 12:11:22 +010045#include "propidl.h" /* for LPSAFEARRAY_User* functions */
Marcus Meissner0749fc22002-02-05 18:11:17 +000046#include "typelib.h"
Robert Shearman799ebfc2006-01-27 12:54:03 +010047#include "variant.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000048#include "wine/debug.h"
Marcus Meissner0749fc22002-02-05 18:11:17 +000049
Marcus Meissnere6260a32005-03-27 17:51:59 +000050static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0};
Marcus Meissner0749fc22002-02-05 18:11:17 +000051
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000052WINE_DEFAULT_DEBUG_CHANNEL(ole);
53WINE_DECLARE_DEBUG_CHANNEL(olerelay);
Marcus Meissner0749fc22002-02-05 18:11:17 +000054
Alexandre Julliard936198c2004-08-13 00:44:22 +000055#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
56
Marcus Meissner0749fc22002-02-05 18:11:17 +000057typedef struct _marshal_state {
58 LPBYTE base;
59 int size;
60 int curoff;
Marcus Meissner0749fc22002-02-05 18:11:17 +000061} marshal_state;
62
Mike Hearnd440ca42004-06-17 23:03:26 +000063/* used in the olerelay code to avoid having the L"" stuff added by debugstr_w */
64static char *relaystr(WCHAR *in) {
65 char *tmp = (char *)debugstr_w(in);
66 tmp += 2;
67 tmp[strlen(tmp)-1] = '\0';
68 return tmp;
69}
70
Marcus Meissner0749fc22002-02-05 18:11:17 +000071static HRESULT
Huw Daviesd0bdf682006-05-10 11:55:37 +010072xbuf_resize(marshal_state *buf, DWORD newsize)
73{
74 if(buf->size >= newsize)
75 return S_FALSE;
76
77 if(buf->base)
78 {
79 buf->base = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buf->base, newsize);
80 if(!buf->base)
81 return E_OUTOFMEMORY;
82 }
83 else
84 {
85 buf->base = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newsize);
86 if(!buf->base)
87 return E_OUTOFMEMORY;
88 }
Huw Davies3dce3232006-05-15 10:02:48 +010089 buf->size = newsize;
Huw Daviesd0bdf682006-05-10 11:55:37 +010090 return S_OK;
91}
92
93static HRESULT
94xbuf_add(marshal_state *buf, LPBYTE stuff, DWORD size)
95{
96 HRESULT hr;
97
98 if(buf->size - buf->curoff < size)
99 {
100 hr = xbuf_resize(buf, buf->size + size + 100);
101 if(FAILED(hr)) return hr;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000102 }
103 memcpy(buf->base+buf->curoff,stuff,size);
104 buf->curoff += size;
105 return S_OK;
106}
107
108static HRESULT
109xbuf_get(marshal_state *buf, LPBYTE stuff, DWORD size) {
110 if (buf->size < buf->curoff+size) return E_FAIL;
111 memcpy(stuff,buf->base+buf->curoff,size);
112 buf->curoff += size;
113 return S_OK;
114}
115
116static HRESULT
117xbuf_skip(marshal_state *buf, DWORD size) {
118 if (buf->size < buf->curoff+size) return E_FAIL;
119 buf->curoff += size;
120 return S_OK;
121}
122
123static HRESULT
124_unmarshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN *pUnk) {
125 IStream *pStm;
126 ULARGE_INTEGER newpos;
127 LARGE_INTEGER seekto;
128 ULONG res;
129 HRESULT hres;
130 DWORD xsize;
131
132 TRACE("...%s...\n",debugstr_guid(riid));
Mike Hearn64eac752005-01-27 11:11:32 +0000133
Marcus Meissner0749fc22002-02-05 18:11:17 +0000134 *pUnk = NULL;
135 hres = xbuf_get(buf,(LPBYTE)&xsize,sizeof(xsize));
Mike Hearn64eac752005-01-27 11:11:32 +0000136 if (hres) {
137 ERR("xbuf_get failed\n");
138 return hres;
139 }
140
Marcus Meissner0749fc22002-02-05 18:11:17 +0000141 if (xsize == 0) return S_OK;
Mike Hearn64eac752005-01-27 11:11:32 +0000142
Marcus Meissner0749fc22002-02-05 18:11:17 +0000143 hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
144 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +0000145 ERR("Stream create failed %lx\n",hres);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000146 return hres;
147 }
Mike Hearn64eac752005-01-27 11:11:32 +0000148
Marcus Meissner0749fc22002-02-05 18:11:17 +0000149 hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res);
Mike Hearn64eac752005-01-27 11:11:32 +0000150 if (hres) {
151 ERR("stream write %lx\n",hres);
152 return hres;
153 }
154
Marcus Meissner0749fc22002-02-05 18:11:17 +0000155 memset(&seekto,0,sizeof(seekto));
156 hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
Mike Hearn64eac752005-01-27 11:11:32 +0000157 if (hres) {
158 ERR("Failed Seek %lx\n",hres);
159 return hres;
160 }
161
Marcus Meissner0749fc22002-02-05 18:11:17 +0000162 hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk);
163 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +0000164 ERR("Unmarshalling interface %s failed with %lx\n",debugstr_guid(riid),hres);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000165 return hres;
166 }
Mike Hearn64eac752005-01-27 11:11:32 +0000167
Marcus Meissner0749fc22002-02-05 18:11:17 +0000168 IStream_Release(pStm);
169 return xbuf_skip(buf,xsize);
170}
171
172static HRESULT
173_marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) {
Mike Hearn64eac752005-01-27 11:11:32 +0000174 LPBYTE tempbuf = NULL;
175 IStream *pStm = NULL;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000176 STATSTG ststg;
177 ULARGE_INTEGER newpos;
178 LARGE_INTEGER seekto;
179 ULONG res;
180 DWORD xsize;
181 HRESULT hres;
182
Mike Hearn64eac752005-01-27 11:11:32 +0000183 if (!pUnk) {
Marcus Meissner41079862005-03-29 13:06:44 +0000184 /* this is valid, if for instance we serialize
185 * a VT_DISPATCH with NULL ptr which apparently
186 * can happen. S_OK to make sure we continue
187 * serializing.
188 */
Robert Shearman89846942006-01-18 11:29:01 +0100189 WARN("pUnk is NULL\n");
Marcus Meissner41079862005-03-29 13:06:44 +0000190 xsize = 0;
191 return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
Mike Hearn64eac752005-01-27 11:11:32 +0000192 }
Marcus Meissner0749fc22002-02-05 18:11:17 +0000193
Marcus Meissner41079862005-03-29 13:06:44 +0000194 hres = E_FAIL;
195
Marcus Meissner0749fc22002-02-05 18:11:17 +0000196 TRACE("...%s...\n",debugstr_guid(riid));
Mike Hearn64eac752005-01-27 11:11:32 +0000197
Marcus Meissner0749fc22002-02-05 18:11:17 +0000198 hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
199 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +0000200 ERR("Stream create failed %lx\n",hres);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000201 goto fail;
202 }
Mike Hearn64eac752005-01-27 11:11:32 +0000203
Robert Shearman4519b1b2005-08-24 09:44:41 +0000204 hres = CoMarshalInterface(pStm,riid,pUnk,0,NULL,0);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000205 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +0000206 ERR("Marshalling interface %s failed with %lx\n", debugstr_guid(riid), hres);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000207 goto fail;
208 }
Mike Hearn64eac752005-01-27 11:11:32 +0000209
Marcus Meissner0749fc22002-02-05 18:11:17 +0000210 hres = IStream_Stat(pStm,&ststg,0);
Mike Hearn64eac752005-01-27 11:11:32 +0000211 if (hres) {
212 ERR("Stream stat failed\n");
213 goto fail;
214 }
215
Ge van Geldorp399901e2004-01-23 01:51:33 +0000216 tempbuf = HeapAlloc(GetProcessHeap(), 0, ststg.cbSize.u.LowPart);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000217 memset(&seekto,0,sizeof(seekto));
218 hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
Mike Hearn64eac752005-01-27 11:11:32 +0000219 if (hres) {
220 ERR("Failed Seek %lx\n",hres);
221 goto fail;
222 }
223
Ge van Geldorp399901e2004-01-23 01:51:33 +0000224 hres = IStream_Read(pStm,tempbuf,ststg.cbSize.u.LowPart,&res);
Mike Hearn64eac752005-01-27 11:11:32 +0000225 if (hres) {
226 ERR("Failed Read %lx\n",hres);
227 goto fail;
228 }
229
Ge van Geldorp399901e2004-01-23 01:51:33 +0000230 xsize = ststg.cbSize.u.LowPart;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000231 xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
Ge van Geldorp399901e2004-01-23 01:51:33 +0000232 hres = xbuf_add(buf,tempbuf,ststg.cbSize.u.LowPart);
Mike Hearn64eac752005-01-27 11:11:32 +0000233
Marcus Meissner0749fc22002-02-05 18:11:17 +0000234 HeapFree(GetProcessHeap(),0,tempbuf);
Mike Hearn64eac752005-01-27 11:11:32 +0000235 IStream_Release(pStm);
236
Marcus Meissner0749fc22002-02-05 18:11:17 +0000237 return hres;
Mike Hearn64eac752005-01-27 11:11:32 +0000238
Marcus Meissner0749fc22002-02-05 18:11:17 +0000239fail:
240 xsize = 0;
241 xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
Mike Hearn64eac752005-01-27 11:11:32 +0000242 if (pStm) IUnknown_Release(pStm);
Mike Hearn64eac752005-01-27 11:11:32 +0000243 HeapFree(GetProcessHeap(), 0, tempbuf);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000244 return hres;
245}
246
247/********************* OLE Proxy/Stub Factory ********************************/
248static HRESULT WINAPI
249PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) {
250 if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) {
Vincent Béron9a624912002-05-31 23:06:46 +0000251 *ppv = (LPVOID)iface;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000252 /* No ref counting, static class */
253 return S_OK;
254 }
255 FIXME("(%s) unknown IID?\n",debugstr_guid(iid));
256 return E_NOINTERFACE;
257}
258
259static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; }
260static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; }
261
262static HRESULT
263_get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
264 HRESULT hres;
265 HKEY ikey;
266 char tlguid[200],typelibkey[300],interfacekey[300],ver[100];
267 char tlfn[260];
268 OLECHAR tlfnW[260];
Mike McCormackd7b9a232005-07-06 19:08:05 +0000269 DWORD tlguidlen, verlen, type;
270 LONG tlfnlen;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000271 ITypeLib *tl;
272
273 sprintf( interfacekey, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
274 riid->Data1, riid->Data2, riid->Data3,
275 riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
276 riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]
277 );
278
279 if (RegOpenKeyA(HKEY_CLASSES_ROOT,interfacekey,&ikey)) {
Mike Hearn64eac752005-01-27 11:11:32 +0000280 ERR("No %s key found.\n",interfacekey);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000281 return E_FAIL;
282 }
283 type = (1<<REG_SZ);
284 tlguidlen = sizeof(tlguid);
Mike McCormackd7b9a232005-07-06 19:08:05 +0000285 if (RegQueryValueExA(ikey,NULL,NULL,&type,(LPBYTE)tlguid,&tlguidlen)) {
Mike Hearn64eac752005-01-27 11:11:32 +0000286 ERR("Getting typelib guid failed.\n");
Marcus Meissner0749fc22002-02-05 18:11:17 +0000287 RegCloseKey(ikey);
288 return E_FAIL;
289 }
290 type = (1<<REG_SZ);
291 verlen = sizeof(ver);
Mike McCormackd7b9a232005-07-06 19:08:05 +0000292 if (RegQueryValueExA(ikey,"Version",NULL,&type,(LPBYTE)ver,&verlen)) {
Mike Hearn64eac752005-01-27 11:11:32 +0000293 ERR("Could not get version value?\n");
Marcus Meissner0749fc22002-02-05 18:11:17 +0000294 RegCloseKey(ikey);
295 return E_FAIL;
296 }
297 RegCloseKey(ikey);
298 sprintf(typelibkey,"Typelib\\%s\\%s\\0\\win32",tlguid,ver);
299 tlfnlen = sizeof(tlfn);
300 if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) {
Mike Hearn64eac752005-01-27 11:11:32 +0000301 ERR("Could not get typelib fn?\n");
Marcus Meissner0749fc22002-02-05 18:11:17 +0000302 return E_FAIL;
303 }
Thomas Weidenmueller05d62922006-05-12 00:07:59 +0200304 MultiByteToWideChar(CP_ACP, 0, tlfn, -1, tlfnW, sizeof(tlfnW) / sizeof(tlfnW[0]));
Marcus Meissner0749fc22002-02-05 18:11:17 +0000305 hres = LoadTypeLib(tlfnW,&tl);
306 if (hres) {
307 ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid));
308 return hres;
309 }
310 hres = ITypeLib_GetTypeInfoOfGuid(tl,riid,ti);
311 if (hres) {
312 ERR("typelib does not contain info for %s?\n",debugstr_guid(riid));
313 ITypeLib_Release(tl);
314 return hres;
315 }
316 /* FIXME: do this? ITypeLib_Release(tl); */
317 return hres;
318}
319
320/* Determine nr of functions. Since we use the toplevel interface and all
Vincent Béron9a624912002-05-31 23:06:46 +0000321 * inherited ones have lower numbers, we are ok to not to descent into
Marcus Meissner0749fc22002-02-05 18:11:17 +0000322 * the inheritance tree I think.
323 */
324static int _nroffuncs(ITypeInfo *tinfo) {
325 int n, max = 0;
Robert Shearmanb0d8e06c2005-12-06 21:24:19 +0100326 const FUNCDESC *fdesc;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000327 HRESULT hres;
328
329 n=0;
330 while (1) {
Robert Shearmanb0d8e06c2005-12-06 21:24:19 +0100331 hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo,n,&fdesc);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000332 if (hres)
333 return max+1;
Marcus Meissner995389e2003-09-22 19:21:32 +0000334 if (fdesc->oVft/4 > max)
335 max = fdesc->oVft/4;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000336 n++;
337 }
338 /*NOTREACHED*/
339}
340
Robert Shearman2a54aac2004-09-07 20:42:26 +0000341#ifdef __i386__
342
Alexandre Julliarde8283082004-01-09 22:18:49 +0000343#include "pshpack1.h"
344
Marcus Meissner0749fc22002-02-05 18:11:17 +0000345typedef struct _TMAsmProxy {
346 BYTE popleax;
347 BYTE pushlval;
348 BYTE nr;
349 BYTE pushleax;
350 BYTE lcall;
351 DWORD xcall;
352 BYTE lret;
353 WORD bytestopop;
Alexandre Julliarde8283082004-01-09 22:18:49 +0000354} TMAsmProxy;
355
356#include "poppack.h"
Marcus Meissner0749fc22002-02-05 18:11:17 +0000357
Robert Shearman2a54aac2004-09-07 20:42:26 +0000358#else /* __i386__ */
Pierre d'Herbemontf26e8092005-10-19 19:06:49 +0000359# warning You need to implement stubless proxies for your architecture
360typedef struct _TMAsmProxy {
361} TMAsmProxy;
Robert Shearman2a54aac2004-09-07 20:42:26 +0000362#endif
363
Marcus Meissner0749fc22002-02-05 18:11:17 +0000364typedef struct _TMProxyImpl {
Dmitry Timoshkoveba47f12005-06-06 19:50:35 +0000365 LPVOID *lpvtbl;
366 const IRpcProxyBufferVtbl *lpvtbl2;
Mike McCormackfc200d02005-07-11 10:25:19 +0000367 LONG ref;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000368
369 TMAsmProxy *asmstubs;
370 ITypeInfo* tinfo;
371 IRpcChannelBuffer* chanbuf;
372 IID iid;
Robert Shearman2a54aac2004-09-07 20:42:26 +0000373 CRITICAL_SECTION crit;
Robert Shearmanac23f2c2005-03-11 10:18:31 +0000374 IUnknown *outerunknown;
Robert Shearman5c2a7082005-10-26 10:12:30 +0000375 IDispatch *dispatch;
Robert Shearmanb0218db2006-02-07 16:26:23 +0100376 IRpcProxyBuffer *dispatch_proxy;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000377} TMProxyImpl;
378
379static HRESULT WINAPI
Robert Shearman2a54aac2004-09-07 20:42:26 +0000380TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv)
381{
Marcus Meissner0749fc22002-02-05 18:11:17 +0000382 TRACE("()\n");
383 if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) {
Robert Shearman2a54aac2004-09-07 20:42:26 +0000384 *ppv = (LPVOID)iface;
385 IRpcProxyBuffer_AddRef(iface);
386 return S_OK;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000387 }
388 FIXME("no interface for %s\n",debugstr_guid(riid));
389 return E_NOINTERFACE;
390}
391
392static ULONG WINAPI
Robert Shearman2a54aac2004-09-07 20:42:26 +0000393TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface)
394{
Marcus Meissner0749fc22002-02-05 18:11:17 +0000395 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
James Hawkinsba92d292005-01-14 16:02:20 +0000396 ULONG refCount = InterlockedIncrement(&This->ref);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000397
James Hawkinsba92d292005-01-14 16:02:20 +0000398 TRACE("(%p)->(ref before=%lu)\n",This, refCount - 1);
Robert Shearman2a54aac2004-09-07 20:42:26 +0000399
James Hawkinsba92d292005-01-14 16:02:20 +0000400 return refCount;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000401}
402
403static ULONG WINAPI
Robert Shearman2a54aac2004-09-07 20:42:26 +0000404TMProxyImpl_Release(LPRPCPROXYBUFFER iface)
405{
Marcus Meissner0749fc22002-02-05 18:11:17 +0000406 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
James Hawkinsba92d292005-01-14 16:02:20 +0000407 ULONG refCount = InterlockedDecrement(&This->ref);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000408
James Hawkinsba92d292005-01-14 16:02:20 +0000409 TRACE("(%p)->(ref before=%lu)\n",This, refCount + 1);
Robert Shearman2a54aac2004-09-07 20:42:26 +0000410
James Hawkinsba92d292005-01-14 16:02:20 +0000411 if (!refCount)
Robert Shearman2a54aac2004-09-07 20:42:26 +0000412 {
Robert Shearmanb0218db2006-02-07 16:26:23 +0100413 if (This->dispatch_proxy) IRpcProxyBuffer_Release(This->dispatch_proxy);
Robert Shearman2a54aac2004-09-07 20:42:26 +0000414 DeleteCriticalSection(&This->crit);
415 if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf);
416 VirtualFree(This->asmstubs, 0, MEM_RELEASE);
417 CoTaskMemFree(This);
418 }
James Hawkinsba92d292005-01-14 16:02:20 +0000419 return refCount;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000420}
421
422static HRESULT WINAPI
423TMProxyImpl_Connect(
Robert Shearman2a54aac2004-09-07 20:42:26 +0000424 LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer)
425{
426 ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000427
Robert Shearman2a54aac2004-09-07 20:42:26 +0000428 TRACE("(%p)\n", pRpcChannelBuffer);
429
430 EnterCriticalSection(&This->crit);
431
432 IRpcChannelBuffer_AddRef(pRpcChannelBuffer);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000433 This->chanbuf = pRpcChannelBuffer;
Robert Shearman2a54aac2004-09-07 20:42:26 +0000434
435 LeaveCriticalSection(&This->crit);
436
Robert Shearmanb0218db2006-02-07 16:26:23 +0100437 if (This->dispatch_proxy)
438 IRpcProxyBuffer_Connect(This->dispatch_proxy, pRpcChannelBuffer);
439
Marcus Meissner0749fc22002-02-05 18:11:17 +0000440 return S_OK;
441}
442
443static void WINAPI
Robert Shearman2a54aac2004-09-07 20:42:26 +0000444TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface)
445{
446 ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000447
Robert Shearman2a54aac2004-09-07 20:42:26 +0000448 TRACE("()\n");
449
450 EnterCriticalSection(&This->crit);
451
Marcus Meissner0749fc22002-02-05 18:11:17 +0000452 IRpcChannelBuffer_Release(This->chanbuf);
453 This->chanbuf = NULL;
Robert Shearman2a54aac2004-09-07 20:42:26 +0000454
455 LeaveCriticalSection(&This->crit);
Robert Shearmanb0218db2006-02-07 16:26:23 +0100456
457 if (This->dispatch_proxy)
458 IRpcProxyBuffer_Disconnect(This->dispatch_proxy);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000459}
460
461
Dmitry Timoshkoveba47f12005-06-06 19:50:35 +0000462static const IRpcProxyBufferVtbl tmproxyvtable = {
Marcus Meissner0749fc22002-02-05 18:11:17 +0000463 TMProxyImpl_QueryInterface,
464 TMProxyImpl_AddRef,
465 TMProxyImpl_Release,
466 TMProxyImpl_Connect,
467 TMProxyImpl_Disconnect
468};
469
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000470/* how much space do we use on stack in DWORD steps. */
Marcus Meissner5539e282004-09-27 20:33:27 +0000471int
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000472_argsize(DWORD vt) {
473 switch (vt) {
Marcus Meissner2045ed22005-11-04 11:13:55 +0000474 case VT_UI8:
475 return 8/sizeof(DWORD);
Robert Shearman1329f872005-06-09 09:43:38 +0000476 case VT_R8:
477 return sizeof(double)/sizeof(DWORD);
478 case VT_CY:
479 return sizeof(CY)/sizeof(DWORD);
Marcus Meissnerc18a6aa2002-06-14 00:36:42 +0000480 case VT_DATE:
481 return sizeof(DATE)/sizeof(DWORD);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000482 case VT_VARIANT:
483 return (sizeof(VARIANT)+3)/sizeof(DWORD);
484 default:
485 return 1;
486 }
487}
488
489static int
490_xsize(TYPEDESC *td) {
491 switch (td->vt) {
Marcus Meissnerc18a6aa2002-06-14 00:36:42 +0000492 case VT_DATE:
493 return sizeof(DATE);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000494 case VT_VARIANT:
495 return sizeof(VARIANT)+3;
496 case VT_CARRAY: {
497 int i, arrsize = 1;
498 ARRAYDESC *adesc = td->u.lpadesc;
499
500 for (i=0;i<adesc->cDims;i++)
501 arrsize *= adesc->rgbounds[i].cElements;
502 return arrsize*_xsize(&adesc->tdescElem);
503 }
Marcus Meissner2045ed22005-11-04 11:13:55 +0000504 case VT_UI8:
505 case VT_I8:
506 return 8;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000507 case VT_UI2:
508 case VT_I2:
509 return 2;
510 case VT_UI1:
511 case VT_I1:
512 return 1;
513 default:
514 return 4;
515 }
516}
517
Marcus Meissner0749fc22002-02-05 18:11:17 +0000518static HRESULT
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000519serialize_param(
520 ITypeInfo *tinfo,
521 BOOL writeit,
522 BOOL debugout,
523 BOOL dealloc,
524 TYPEDESC *tdesc,
525 DWORD *arg,
Robert Shearman2a54aac2004-09-07 20:42:26 +0000526 marshal_state *buf)
527{
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000528 HRESULT hres = S_OK;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000529
Robert Shearman799ebfc2006-01-27 12:54:03 +0100530 TRACE("(tdesc.vt %s)\n",debugstr_vt(tdesc->vt));
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000531
Marcus Meissner0749fc22002-02-05 18:11:17 +0000532 switch (tdesc->vt) {
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000533 case VT_EMPTY: /* nothing. empty variant for instance */
Marcus Meissner0749fc22002-02-05 18:11:17 +0000534 return S_OK;
Marcus Meissner2045ed22005-11-04 11:13:55 +0000535 case VT_I8:
536 case VT_UI8:
Robert Shearman878af662006-01-14 17:47:25 +0100537 case VT_CY:
Marcus Meissner2045ed22005-11-04 11:13:55 +0000538 hres = S_OK;
539 if (debugout) TRACE_(olerelay)("%lx%lx",arg[0],arg[1]);
540 if (writeit)
541 hres = xbuf_add(buf,(LPBYTE)arg,8);
542 return hres;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000543 case VT_BOOL:
544 case VT_ERROR:
Robert Shearmanfd81d9c2006-02-07 16:26:02 +0100545 case VT_INT:
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000546 case VT_UINT:
547 case VT_I4:
Marcus Meissnerd3448492002-12-05 19:12:50 +0000548 case VT_R4:
Alexandre Julliard232760d2005-03-14 10:09:11 +0000549 case VT_UI4:
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000550 hres = S_OK;
Mike Hearnd440ca42004-06-17 23:03:26 +0000551 if (debugout) TRACE_(olerelay)("%lx",*arg);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000552 if (writeit)
553 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
554 return hres;
Marcus Meissnerc91df672005-03-27 18:17:19 +0000555 case VT_I2:
556 case VT_UI2:
557 hres = S_OK;
558 if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);
559 if (writeit)
560 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
561 return hres;
562 case VT_I1:
563 case VT_UI1:
564 hres = S_OK;
565 if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);
566 if (writeit)
567 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
568 return hres;
Marcus Meissner4b5f3c62005-03-29 11:29:11 +0000569 case VT_I4|VT_BYREF:
570 hres = S_OK;
571 if (debugout) TRACE_(olerelay)("&0x%lx",*arg);
572 if (writeit)
573 hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD));
574 /* do not dealloc at this time */
575 return hres;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000576 case VT_VARIANT: {
577 TYPEDESC tdesc2;
578 VARIANT *vt = (VARIANT*)arg;
579 DWORD vttype = V_VT(vt);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000580
Robert Shearman799ebfc2006-01-27 12:54:03 +0100581 if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype));
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000582 tdesc2.vt = vttype;
583 if (writeit) {
584 hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
585 if (hres) return hres;
586 }
587 /* need to recurse since we need to free the stuff */
Mike McCormacka04b77d2005-08-08 18:38:29 +0000588 hres = serialize_param(tinfo,writeit,debugout,dealloc,&tdesc2,(DWORD*)&(V_I4(vt)),buf);
Mike Hearnd440ca42004-06-17 23:03:26 +0000589 if (debugout) TRACE_(olerelay)(")");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000590 return hres;
591 }
Alexandre Julliard232760d2005-03-14 10:09:11 +0000592 case VT_BSTR|VT_BYREF: {
Marcus Meissner4b5f3c62005-03-29 11:29:11 +0000593 if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>");
Alexandre Julliard232760d2005-03-14 10:09:11 +0000594 if (writeit) {
595 /* ptr to ptr to magic widestring, basically */
596 BSTR *bstr = (BSTR *) *arg;
Robert Shearmand8780c72005-07-19 19:42:50 +0000597 DWORD len;
Marcus Meissner4b5f3c62005-03-29 11:29:11 +0000598 if (!*bstr) {
Alexandre Julliard232760d2005-03-14 10:09:11 +0000599 /* -1 means "null string" which is equivalent to empty string */
Robert Shearmand8780c72005-07-19 19:42:50 +0000600 len = -1;
601 hres = xbuf_add(buf, (LPBYTE)&len,sizeof(DWORD));
602 if (hres) return hres;
Alexandre Julliard232760d2005-03-14 10:09:11 +0000603 } else {
Robert Shearmand8780c72005-07-19 19:42:50 +0000604 len = *((DWORD*)*bstr-1)/sizeof(WCHAR);
605 hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
606 if (hres) return hres;
607 hres = xbuf_add(buf,(LPBYTE)*bstr,len * sizeof(WCHAR));
608 if (hres) return hres;
Alexandre Julliard232760d2005-03-14 10:09:11 +0000609 }
610 }
611
612 if (dealloc && arg) {
613 BSTR *str = *((BSTR **)arg);
614 SysFreeString(*str);
615 }
616 return S_OK;
617 }
618
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000619 case VT_BSTR: {
620 if (debugout) {
Mike Hearnedcbd132005-03-27 18:20:10 +0000621 if (*arg)
622 TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg));
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000623 else
Mike Hearnd440ca42004-06-17 23:03:26 +0000624 TRACE_(olerelay)("<bstr NULL>");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000625 }
626 if (writeit) {
Robert Shearmand8780c72005-07-19 19:42:50 +0000627 BSTR bstr = (BSTR)*arg;
628 DWORD len;
629 if (!bstr) {
630 len = -1;
631 hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
632 if (hres) return hres;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000633 } else {
Robert Shearmand8780c72005-07-19 19:42:50 +0000634 len = *((DWORD*)bstr-1)/sizeof(WCHAR);
635 hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
636 if (hres) return hres;
637 hres = xbuf_add(buf,(LPBYTE)bstr,len * sizeof(WCHAR));
638 if (hres) return hres;
Marcus Meissner5b63cc22002-05-06 20:12:11 +0000639 }
Marcus Meissner0749fc22002-02-05 18:11:17 +0000640 }
Marcus Meissner236ad0d2003-12-01 22:36:49 +0000641
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000642 if (dealloc && arg)
Marcus Meissner236ad0d2003-12-01 22:36:49 +0000643 SysFreeString((BSTR)*arg);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000644 return S_OK;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000645 }
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000646 case VT_PTR: {
647 DWORD cookie;
Marcus Meissner6f823db2005-09-07 09:23:04 +0000648 BOOL derefhere = TRUE;
Robert Shearman1329f872005-06-09 09:43:38 +0000649
Marcus Meissner6f823db2005-09-07 09:23:04 +0000650 if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
651 ITypeInfo *tinfo2;
652 TYPEATTR *tattr;
653
654 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
655 if (hres) {
656 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
657 return hres;
658 }
659 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
660 switch (tattr->typekind) {
661 case TKIND_ENUM: /* confirmed */
662 case TKIND_RECORD: /* FIXME: mostly untested */
663 derefhere=TRUE;
664 break;
665 case TKIND_ALIAS: /* FIXME: untested */
666 case TKIND_DISPATCH: /* will be done in VT_USERDEFINED case */
667 case TKIND_INTERFACE: /* will be done in VT_USERDEFINED case */
668 derefhere=FALSE;
669 break;
670 default:
671 FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind);
672 derefhere=FALSE;
673 break;
674 }
675 ITypeInfo_Release(tinfo2);
676 }
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000677
Mike Hearnd440ca42004-06-17 23:03:26 +0000678 if (debugout) TRACE_(olerelay)("*");
Marcus Meissnere6260a32005-03-27 17:51:59 +0000679 /* Write always, so the other side knows when it gets a NULL pointer.
680 */
681 cookie = *arg ? 0x42424242 : 0;
682 hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));
683 if (hres)
684 return hres;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000685 if (!*arg) {
Mike Hearnd440ca42004-06-17 23:03:26 +0000686 if (debugout) TRACE_(olerelay)("NULL");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000687 return S_OK;
688 }
689 hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf);
Robert Shearman1329f872005-06-09 09:43:38 +0000690 if (derefhere && dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000691 return hres;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000692 }
693 case VT_UNKNOWN:
Mike Hearnd440ca42004-06-17 23:03:26 +0000694 if (debugout) TRACE_(olerelay)("unk(0x%lx)",*arg);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000695 if (writeit)
696 hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg);
Robert Shearman9030ff22006-02-14 11:33:03 +0100697 if (dealloc && *(IUnknown **)arg)
Robert Shearmanec5d7392006-02-07 16:25:42 +0100698 IUnknown_Release((LPUNKNOWN)*arg);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000699 return hres;
700 case VT_DISPATCH:
Mike Hearnd440ca42004-06-17 23:03:26 +0000701 if (debugout) TRACE_(olerelay)("idisp(0x%lx)",*arg);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000702 if (writeit)
703 hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg);
Robert Shearman9030ff22006-02-14 11:33:03 +0100704 if (dealloc && *(IUnknown **)arg)
Robert Shearmanec5d7392006-02-07 16:25:42 +0100705 IUnknown_Release((LPUNKNOWN)*arg);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000706 return hres;
707 case VT_VOID:
Mike Hearnd440ca42004-06-17 23:03:26 +0000708 if (debugout) TRACE_(olerelay)("<void>");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000709 return S_OK;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000710 case VT_USERDEFINED: {
711 ITypeInfo *tinfo2;
712 TYPEATTR *tattr;
713
Marcus Meissner0749fc22002-02-05 18:11:17 +0000714 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
715 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +0000716 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000717 return hres;
718 }
719 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
720 switch (tattr->typekind) {
Marcus Meissner26ffca42002-12-12 22:25:07 +0000721 case TKIND_DISPATCH:
Marcus Meissner0749fc22002-02-05 18:11:17 +0000722 case TKIND_INTERFACE:
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000723 if (writeit)
724 hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg);
Robert Shearman4519b1b2005-08-24 09:44:41 +0000725 if (dealloc)
726 IUnknown_Release((LPUNKNOWN)arg);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000727 break;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000728 case TKIND_RECORD: {
729 int i;
Mike Hearnd440ca42004-06-17 23:03:26 +0000730 if (debugout) TRACE_(olerelay)("{");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000731 for (i=0;i<tattr->cVars;i++) {
732 VARDESC *vdesc;
733 ELEMDESC *elem2;
734 TYPEDESC *tdesc2;
735
736 hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
737 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +0000738 ERR("Could not get vardesc of %d\n",i);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000739 return hres;
740 }
741 /* Need them for hack below */
742 /*
743 memset(names,0,sizeof(names));
744 hres = ITypeInfo_GetNames(tinfo2,vdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
745 if (nrofnames > sizeof(names)/sizeof(names[0])) {
746 ERR("Need more names!\n");
747 }
748 if (!hres && debugout)
Mike Hearnd440ca42004-06-17 23:03:26 +0000749 TRACE_(olerelay)("%s=",relaystr(names[0]));
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000750 */
751 elem2 = &vdesc->elemdescVar;
752 tdesc2 = &elem2->tdesc;
753 hres = serialize_param(
754 tinfo2,
755 writeit,
756 debugout,
757 dealloc,
758 tdesc2,
759 (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst),
760 buf
761 );
Robert Shearmanc6296c42005-06-01 11:03:40 +0000762 ITypeInfo_ReleaseVarDesc(tinfo2, vdesc);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000763 if (hres!=S_OK)
764 return hres;
765 if (debugout && (i<(tattr->cVars-1)))
Mike Hearnd440ca42004-06-17 23:03:26 +0000766 TRACE_(olerelay)(",");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000767 }
Mike Hearnd440ca42004-06-17 23:03:26 +0000768 if (debugout) TRACE_(olerelay)("}");
Marcus Meissner0749fc22002-02-05 18:11:17 +0000769 break;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000770 }
Robert Shearmand2e2e852005-07-19 19:13:23 +0000771 case TKIND_ALIAS:
772 return serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf);
773 case TKIND_ENUM:
774 hres = S_OK;
775 if (debugout) TRACE_(olerelay)("%lx",*arg);
776 if (writeit)
777 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
778 return hres;
Marcus Meissner26ffca42002-12-12 22:25:07 +0000779 default:
780 FIXME("Unhandled typekind %d\n",tattr->typekind);
781 hres = E_FAIL;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000782 break;
783 }
784 ITypeInfo_Release(tinfo2);
785 return hres;
786 }
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000787 case VT_CARRAY: {
788 ARRAYDESC *adesc = tdesc->u.lpadesc;
789 int i, arrsize = 1;
790
Mike Hearnd440ca42004-06-17 23:03:26 +0000791 if (debugout) TRACE_(olerelay)("carr");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000792 for (i=0;i<adesc->cDims;i++) {
Mike Hearnd440ca42004-06-17 23:03:26 +0000793 if (debugout) TRACE_(olerelay)("[%ld]",adesc->rgbounds[i].cElements);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000794 arrsize *= adesc->rgbounds[i].cElements;
795 }
Robert Shearman799ebfc2006-01-27 12:54:03 +0100796 if (debugout) TRACE_(olerelay)("(vt %s)",debugstr_vt(adesc->tdescElem.vt));
Mike Hearnd440ca42004-06-17 23:03:26 +0000797 if (debugout) TRACE_(olerelay)("[");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000798 for (i=0;i<arrsize;i++) {
799 hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);
800 if (hres)
801 return hres;
Mike Hearnd440ca42004-06-17 23:03:26 +0000802 if (debugout && (i<arrsize-1)) TRACE_(olerelay)(",");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000803 }
Mike Hearnd440ca42004-06-17 23:03:26 +0000804 if (debugout) TRACE_(olerelay)("]");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000805 return S_OK;
806 }
Huw Davies86d94572006-05-10 12:11:22 +0100807 case VT_SAFEARRAY: {
808 if (writeit)
809 {
810 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
811 unsigned long size = LPSAFEARRAY_UserSize(&flags, buf->curoff, (LPSAFEARRAY *)arg);
812 xbuf_resize(buf, size);
813 LPSAFEARRAY_UserMarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg);
814 buf->curoff = size;
815 }
816 return S_OK;
817 }
Marcus Meissner0749fc22002-02-05 18:11:17 +0000818 default:
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000819 ERR("Unhandled marshal type %d.\n",tdesc->vt);
820 return S_OK;
821 }
822}
823
Marcus Meissner0749fc22002-02-05 18:11:17 +0000824static HRESULT
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000825deserialize_param(
826 ITypeInfo *tinfo,
827 BOOL readit,
828 BOOL debugout,
829 BOOL alloc,
830 TYPEDESC *tdesc,
831 DWORD *arg,
Robert Shearman2a54aac2004-09-07 20:42:26 +0000832 marshal_state *buf)
833{
Marcus Meissner0749fc22002-02-05 18:11:17 +0000834 HRESULT hres = S_OK;
Marcus Meissner0749fc22002-02-05 18:11:17 +0000835
Robert Shearman799ebfc2006-01-27 12:54:03 +0100836 TRACE("vt %s at %p\n",debugstr_vt(tdesc->vt),arg);
Marcus Meissner0749fc22002-02-05 18:11:17 +0000837
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000838 while (1) {
839 switch (tdesc->vt) {
840 case VT_EMPTY:
Mike Hearnd440ca42004-06-17 23:03:26 +0000841 if (debugout) TRACE_(olerelay)("<empty>");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000842 return S_OK;
843 case VT_NULL:
Mike Hearnd440ca42004-06-17 23:03:26 +0000844 if (debugout) TRACE_(olerelay)("<null>");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000845 return S_OK;
846 case VT_VARIANT: {
847 VARIANT *vt = (VARIANT*)arg;
848
849 if (readit) {
850 DWORD vttype;
851 TYPEDESC tdesc2;
852 hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype));
853 if (hres) {
854 FIXME("vt type not read?\n");
855 return hres;
856 }
857 memset(&tdesc2,0,sizeof(tdesc2));
858 tdesc2.vt = vttype;
859 V_VT(vt) = vttype;
Robert Shearman799ebfc2006-01-27 12:54:03 +0100860 if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype));
Mike McCormacka04b77d2005-08-08 18:38:29 +0000861 hres = deserialize_param(tinfo, readit, debugout, alloc, &tdesc2, (DWORD*)&(V_I4(vt)), buf);
Mike Hearnd440ca42004-06-17 23:03:26 +0000862 TRACE_(olerelay)(")");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000863 return hres;
864 } else {
865 VariantInit(vt);
866 return S_OK;
867 }
868 }
Marcus Meissner2045ed22005-11-04 11:13:55 +0000869 case VT_I8:
870 case VT_UI8:
Robert Shearman878af662006-01-14 17:47:25 +0100871 case VT_CY:
Marcus Meissner2045ed22005-11-04 11:13:55 +0000872 if (readit) {
873 hres = xbuf_get(buf,(LPBYTE)arg,8);
874 if (hres) ERR("Failed to read integer 8 byte\n");
875 }
876 if (debugout) TRACE_(olerelay)("%lx%lx",arg[0],arg[1]);
877 return hres;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000878 case VT_ERROR:
Alexandre Julliard232760d2005-03-14 10:09:11 +0000879 case VT_BOOL:
880 case VT_I4:
Robert Shearmanfd81d9c2006-02-07 16:26:02 +0100881 case VT_INT:
Alexandre Julliard232760d2005-03-14 10:09:11 +0000882 case VT_UINT:
883 case VT_R4:
884 case VT_UI4:
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000885 if (readit) {
886 hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
Mike Hearn64eac752005-01-27 11:11:32 +0000887 if (hres) ERR("Failed to read integer 4 byte\n");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000888 }
Mike Hearnd440ca42004-06-17 23:03:26 +0000889 if (debugout) TRACE_(olerelay)("%lx",*arg);
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000890 return hres;
Marcus Meissnerc91df672005-03-27 18:17:19 +0000891 case VT_I2:
892 case VT_UI2:
893 if (readit) {
894 DWORD x;
895 hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
896 if (hres) ERR("Failed to read integer 4 byte\n");
897 memcpy(arg,&x,2);
898 }
899 if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);
900 return hres;
901 case VT_I1:
902 case VT_UI1:
903 if (readit) {
904 DWORD x;
905 hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
906 if (hres) ERR("Failed to read integer 4 byte\n");
907 memcpy(arg,&x,1);
908 }
909 if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);
910 return hres;
Marcus Meissner4b5f3c62005-03-29 11:29:11 +0000911 case VT_I4|VT_BYREF:
912 hres = S_OK;
913 if (alloc)
914 *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
915 if (readit) {
916 hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD));
917 if (hres) ERR("Failed to read integer 4 byte\n");
918 }
919 if (debugout) TRACE_(olerelay)("&0x%lx",*(DWORD*)*arg);
920 return hres;
Alexandre Julliard232760d2005-03-14 10:09:11 +0000921 case VT_BSTR|VT_BYREF: {
922 BSTR **bstr = (BSTR **)arg;
923 WCHAR *str;
924 DWORD len;
925
926 if (readit) {
927 hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
928 if (hres) {
929 ERR("failed to read bstr klen\n");
930 return hres;
931 }
932 if (len == -1) {
Marcus Meissner4b5f3c62005-03-29 11:29:11 +0000933 *bstr = CoTaskMemAlloc(sizeof(BSTR *));
934 **bstr = NULL;
Alexandre Julliard232760d2005-03-14 10:09:11 +0000935 if (debugout) TRACE_(olerelay)("<bstr NULL>");
936 } else {
Robert Shearmand8780c72005-07-19 19:42:50 +0000937 str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
938 hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
Alexandre Julliard232760d2005-03-14 10:09:11 +0000939 if (hres) {
940 ERR("Failed to read BSTR.\n");
941 return hres;
942 }
943 *bstr = CoTaskMemAlloc(sizeof(BSTR *));
944 **bstr = SysAllocStringLen(str,len);
945 if (debugout) TRACE_(olerelay)("%s",relaystr(str));
946 HeapFree(GetProcessHeap(),0,str);
947 }
948 } else {
949 *bstr = NULL;
950 }
951 return S_OK;
952 }
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000953 case VT_BSTR: {
954 WCHAR *str;
955 DWORD len;
956
957 if (readit) {
958 hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
959 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +0000960 ERR("failed to read bstr klen\n");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000961 return hres;
962 }
963 if (len == -1) {
964 *arg = 0;
Mike Hearnd440ca42004-06-17 23:03:26 +0000965 if (debugout) TRACE_(olerelay)("<bstr NULL>");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000966 } else {
Robert Shearmand8780c72005-07-19 19:42:50 +0000967 str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
968 hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000969 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +0000970 ERR("Failed to read BSTR.\n");
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000971 return hres;
972 }
973 *arg = (DWORD)SysAllocStringLen(str,len);
Mike Hearnd440ca42004-06-17 23:03:26 +0000974 if (debugout) TRACE_(olerelay)("%s",relaystr(str));
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000975 HeapFree(GetProcessHeap(),0,str);
976 }
977 } else {
978 *arg = 0;
979 }
980 return S_OK;
981 }
982 case VT_PTR: {
983 DWORD cookie;
Marcus Meissner6f823db2005-09-07 09:23:04 +0000984 BOOL derefhere = TRUE;
Marcus Meissnere81f10c2002-06-10 02:30:20 +0000985
Marcus Meissner6f823db2005-09-07 09:23:04 +0000986 if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
987 ITypeInfo *tinfo2;
988 TYPEATTR *tattr;
989
990 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
991 if (hres) {
992 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
993 return hres;
994 }
995 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
996 switch (tattr->typekind) {
997 case TKIND_ENUM: /* confirmed */
998 case TKIND_RECORD: /* FIXME: mostly untested */
999 derefhere=TRUE;
1000 break;
1001 case TKIND_ALIAS: /* FIXME: untested */
1002 case TKIND_DISPATCH: /* will be done in VT_USERDEFINED case */
1003 case TKIND_INTERFACE: /* will be done in VT_USERDEFINED case */
1004 derefhere=FALSE;
1005 break;
1006 default:
1007 FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind);
1008 derefhere=FALSE;
1009 break;
1010 }
1011 ITypeInfo_Release(tinfo2);
1012 }
Marcus Meissnere6260a32005-03-27 17:51:59 +00001013 /* read it in all cases, we need to know if we have
1014 * NULL pointer or not.
1015 */
1016 hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));
1017 if (hres) {
1018 ERR("Failed to load pointer cookie.\n");
1019 return hres;
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001020 }
Marcus Meissnere6260a32005-03-27 17:51:59 +00001021 if (cookie != 0x42424242) {
1022 /* we read a NULL ptr from the remote side */
1023 if (debugout) TRACE_(olerelay)("NULL");
1024 *arg = 0;
1025 return S_OK;
1026 }
1027 if (debugout) TRACE_(olerelay)("*");
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001028 if (alloc) {
Marcus Meissnere6260a32005-03-27 17:51:59 +00001029 /* Allocate space for the referenced struct */
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001030 if (derefhere)
1031 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc));
1032 }
1033 if (derefhere)
1034 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, (LPDWORD)*arg, buf);
1035 else
1036 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, arg, buf);
1037 }
1038 case VT_UNKNOWN:
1039 /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */
1040 if (alloc)
1041 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
1042 hres = S_OK;
1043 if (readit)
1044 hres = _unmarshal_interface(buf,&IID_IUnknown,(LPUNKNOWN*)arg);
1045 if (debugout)
Mike Hearnd440ca42004-06-17 23:03:26 +00001046 TRACE_(olerelay)("unk(%p)",arg);
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001047 return hres;
1048 case VT_DISPATCH:
1049 hres = S_OK;
1050 if (readit)
1051 hres = _unmarshal_interface(buf,&IID_IDispatch,(LPUNKNOWN*)arg);
1052 if (debugout)
Mike Hearnd440ca42004-06-17 23:03:26 +00001053 TRACE_(olerelay)("idisp(%p)",arg);
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001054 return hres;
1055 case VT_VOID:
Mike Hearnd440ca42004-06-17 23:03:26 +00001056 if (debugout) TRACE_(olerelay)("<void>");
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001057 return S_OK;
1058 case VT_USERDEFINED: {
1059 ITypeInfo *tinfo2;
1060 TYPEATTR *tattr;
1061
1062 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
1063 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001064 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001065 return hres;
1066 }
1067 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
1068 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001069 ERR("Could not get typeattr in VT_USERDEFINED.\n");
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001070 } else {
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001071 switch (tattr->typekind) {
Marcus Meissner26ffca42002-12-12 22:25:07 +00001072 case TKIND_DISPATCH:
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001073 case TKIND_INTERFACE:
1074 if (readit)
1075 hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);
1076 break;
1077 case TKIND_RECORD: {
1078 int i;
1079
Alexandre Julliard232760d2005-03-14 10:09:11 +00001080 if (alloc)
1081 *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance);
1082
Mike Hearnd440ca42004-06-17 23:03:26 +00001083 if (debugout) TRACE_(olerelay)("{");
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001084 for (i=0;i<tattr->cVars;i++) {
1085 VARDESC *vdesc;
1086
1087 hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
1088 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001089 ERR("Could not get vardesc of %d\n",i);
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001090 return hres;
1091 }
1092 hres = deserialize_param(
1093 tinfo2,
1094 readit,
1095 debugout,
1096 alloc,
1097 &vdesc->elemdescVar.tdesc,
1098 (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst),
1099 buf
1100 );
Robert Shearmanb0d8e06c2005-12-06 21:24:19 +01001101 ITypeInfo2_ReleaseVarDesc(tinfo2, vdesc);
Mike Hearnd440ca42004-06-17 23:03:26 +00001102 if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(",");
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001103 }
Mike Hearnd440ca42004-06-17 23:03:26 +00001104 if (debugout) TRACE_(olerelay)("}");
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001105 break;
1106 }
Robert Shearmand2e2e852005-07-19 19:13:23 +00001107 case TKIND_ALIAS:
1108 return deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf);
1109 case TKIND_ENUM:
1110 if (readit) {
1111 hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
1112 if (hres) ERR("Failed to read enum (4 byte)\n");
1113 }
1114 if (debugout) TRACE_(olerelay)("%lx",*arg);
1115 return hres;
Marcus Meissner26ffca42002-12-12 22:25:07 +00001116 default:
1117 ERR("Unhandled typekind %d\n",tattr->typekind);
1118 hres = E_FAIL;
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001119 break;
1120 }
1121 }
1122 if (hres)
Mike Hearn64eac752005-01-27 11:11:32 +00001123 ERR("failed to stuballoc in TKIND_RECORD.\n");
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001124 ITypeInfo_Release(tinfo2);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001125 return hres;
1126 }
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001127 case VT_CARRAY: {
1128 /* arg is pointing to the start of the array. */
1129 ARRAYDESC *adesc = tdesc->u.lpadesc;
1130 int arrsize,i;
1131 arrsize = 1;
1132 if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n");
1133 for (i=0;i<adesc->cDims;i++)
1134 arrsize *= adesc->rgbounds[i].cElements;
1135 for (i=0;i<arrsize;i++)
1136 deserialize_param(
1137 tinfo,
1138 readit,
1139 debugout,
1140 alloc,
1141 &adesc->tdescElem,
1142 (DWORD*)((LPBYTE)(arg)+i*_xsize(&adesc->tdescElem)),
1143 buf
1144 );
1145 return S_OK;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001146 }
Huw Davies86d94572006-05-10 12:11:22 +01001147 case VT_SAFEARRAY: {
1148 if (readit)
1149 {
1150 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
1151 unsigned char *buffer;
1152 buffer = LPSAFEARRAY_UserUnmarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg);
1153 buf->curoff = buffer - buf->base;
1154 }
1155 return S_OK;
1156 }
Marcus Meissner0749fc22002-02-05 18:11:17 +00001157 default:
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001158 ERR("No handler for VT type %d!\n",tdesc->vt);
1159 return S_OK;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001160 }
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001161 }
1162}
1163
Marcus Meissner0749fc22002-02-05 18:11:17 +00001164/* Searches function, also in inherited interfaces */
1165static HRESULT
1166_get_funcdesc(
Robert Shearmanb0d8e06c2005-12-06 21:24:19 +01001167 ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc, BSTR *iname, BSTR *fname)
Robert Shearman2a54aac2004-09-07 20:42:26 +00001168{
Marcus Meissner0749fc22002-02-05 18:11:17 +00001169 int i = 0, j = 0;
1170 HRESULT hres;
1171
1172 if (fname) *fname = NULL;
1173 if (iname) *iname = NULL;
1174
Robert Shearmanc6296c42005-06-01 11:03:40 +00001175 *tactual = tinfo;
1176 ITypeInfo_AddRef(*tactual);
1177
Marcus Meissner0749fc22002-02-05 18:11:17 +00001178 while (1) {
Robert Shearmanb0d8e06c2005-12-06 21:24:19 +01001179 hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i, fdesc);
1180
Marcus Meissner0749fc22002-02-05 18:11:17 +00001181 if (hres) {
1182 ITypeInfo *tinfo2;
1183 HREFTYPE href;
1184 TYPEATTR *attr;
1185
1186 hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
1187 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001188 ERR("GetTypeAttr failed with %lx\n",hres);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001189 return hres;
1190 }
1191 /* Not found, so look in inherited ifaces. */
1192 for (j=0;j<attr->cImplTypes;j++) {
1193 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);
1194 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001195 ERR("Did not find a reftype for interface offset %d?\n",j);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001196 break;
1197 }
1198 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
1199 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001200 ERR("Did not find a typeinfo for reftype %ld?\n",href);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001201 continue;
1202 }
Robert Shearmanc6296c42005-06-01 11:03:40 +00001203 hres = _get_funcdesc(tinfo2,iMethod,tactual,fdesc,iname,fname);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001204 ITypeInfo_Release(tinfo2);
1205 if (!hres) return S_OK;
1206 }
Mike Hearn6c093f32005-01-26 19:42:17 +00001207 return hres;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001208 }
1209 if (((*fdesc)->oVft/4) == iMethod) {
1210 if (fname)
1211 ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL);
1212 if (iname)
1213 ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL);
1214 return S_OK;
1215 }
1216 i++;
1217 }
Marcus Meissner0749fc22002-02-05 18:11:17 +00001218}
1219
Marcus Meissner0749fc22002-02-05 18:11:17 +00001220static DWORD
Robert Shearman2a54aac2004-09-07 20:42:26 +00001221xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
1222{
Marcus Meissner0749fc22002-02-05 18:11:17 +00001223 DWORD *args = ((DWORD*)&tpinfo)+1, *xargs;
Robert Shearmanb0d8e06c2005-12-06 21:24:19 +01001224 const FUNCDESC *fdesc;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001225 HRESULT hres;
1226 int i, relaydeb = TRACE_ON(olerelay);
1227 marshal_state buf;
1228 RPCOLEMESSAGE msg;
1229 ULONG status;
1230 BSTR fname,iname;
1231 BSTR names[10];
Mike McCormacka04b77d2005-08-08 18:38:29 +00001232 UINT nrofnames;
Marcus Meissner89feaca2005-03-28 10:00:49 +00001233 DWORD remoteresult = 0;
Robert Shearmanc6296c42005-06-01 11:03:40 +00001234 ITypeInfo *tinfo;
Robert Shearmanefe606f2005-11-02 20:00:00 +00001235 IRpcChannelBuffer *chanbuf;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001236
Robert Shearman2a54aac2004-09-07 20:42:26 +00001237 EnterCriticalSection(&tpinfo->crit);
1238
Robert Shearmanc6296c42005-06-01 11:03:40 +00001239 hres = _get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001240 if (hres) {
Robert Shearmanefe606f2005-11-02 20:00:00 +00001241 ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
Robert Shearmanc6296c42005-06-01 11:03:40 +00001242 ITypeInfo_Release(tinfo);
Robert Shearman2a54aac2004-09-07 20:42:26 +00001243 LeaveCriticalSection(&tpinfo->crit);
Robert Shearmanefe606f2005-11-02 20:00:00 +00001244 return E_FAIL;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001245 }
1246
Robert Shearman67942792004-12-14 11:44:11 +00001247 if (!tpinfo->chanbuf)
1248 {
1249 WARN("Tried to use disconnected proxy\n");
Robert Shearmanc6296c42005-06-01 11:03:40 +00001250 ITypeInfo_Release(tinfo);
Robert Shearman67942792004-12-14 11:44:11 +00001251 LeaveCriticalSection(&tpinfo->crit);
1252 return RPC_E_DISCONNECTED;
1253 }
Robert Shearmanefe606f2005-11-02 20:00:00 +00001254 chanbuf = tpinfo->chanbuf;
1255 IRpcChannelBuffer_AddRef(chanbuf);
1256
1257 LeaveCriticalSection(&tpinfo->crit);
Robert Shearman67942792004-12-14 11:44:11 +00001258
Marcus Meissner0749fc22002-02-05 18:11:17 +00001259 if (relaydeb) {
Mike Hearn86cc2d52004-06-23 00:10:29 +00001260 TRACE_(olerelay)("->");
Marcus Meissner0749fc22002-02-05 18:11:17 +00001261 if (iname)
Mike Hearnd440ca42004-06-17 23:03:26 +00001262 TRACE_(olerelay)("%s:",relaystr(iname));
Marcus Meissner0749fc22002-02-05 18:11:17 +00001263 if (fname)
Mike Hearnd440ca42004-06-17 23:03:26 +00001264 TRACE_(olerelay)("%s(%d)",relaystr(fname),method);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001265 else
Mike Hearnd440ca42004-06-17 23:03:26 +00001266 TRACE_(olerelay)("%d",method);
1267 TRACE_(olerelay)("(");
Marcus Meissner0749fc22002-02-05 18:11:17 +00001268 }
Marcus Meissnere6260a32005-03-27 17:51:59 +00001269
1270 if (iname) SysFreeString(iname);
1271 if (fname) SysFreeString(fname);
1272
1273 memset(&buf,0,sizeof(buf));
Marcus Meissnere6260a32005-03-27 17:51:59 +00001274
1275 /* normal typelib driven serializing */
1276
Marcus Meissner0749fc22002-02-05 18:11:17 +00001277 /* Need them for hack below */
1278 memset(names,0,sizeof(names));
Robert Shearmanc6296c42005-06-01 11:03:40 +00001279 if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001280 nrofnames = 0;
1281 if (nrofnames > sizeof(names)/sizeof(names[0]))
Marcus Meissner0749fc22002-02-05 18:11:17 +00001282 ERR("Need more names!\n");
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001283
Marcus Meissnere6260a32005-03-27 17:51:59 +00001284 xargs = args;
1285 for (i=0;i<fdesc->cParams;i++) {
1286 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
Marcus Meissnere6260a32005-03-27 17:51:59 +00001287 if (relaydeb) {
1288 if (i) TRACE_(olerelay)(",");
1289 if (i+1<nrofnames && names[i+1])
1290 TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1291 }
1292 /* No need to marshal other data than FIN and any VT_PTR. */
Huw Davies0c6d5462005-10-26 12:06:49 +00001293 if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags) && (elem->tdesc.vt != VT_PTR)) {
Marcus Meissnere6260a32005-03-27 17:51:59 +00001294 xargs+=_argsize(elem->tdesc.vt);
1295 if (relaydeb) TRACE_(olerelay)("[out]");
1296 continue;
1297 }
Robert Shearman5c2a7082005-10-26 10:12:30 +00001298 hres = serialize_param(
1299 tinfo,
Huw Davies0c6d5462005-10-26 12:06:49 +00001300 elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
Robert Shearman5c2a7082005-10-26 10:12:30 +00001301 relaydeb,
1302 FALSE,
1303 &elem->tdesc,
1304 xargs,
1305 &buf
1306 );
Marcus Meissnere6260a32005-03-27 17:51:59 +00001307
1308 if (hres) {
1309 ERR("Failed to serialize param, hres %lx\n",hres);
1310 break;
1311 }
1312 xargs+=_argsize(elem->tdesc.vt);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001313 }
Mike Hearnd440ca42004-06-17 23:03:26 +00001314 if (relaydeb) TRACE_(olerelay)(")");
Marcus Meissnere6260a32005-03-27 17:51:59 +00001315
Marcus Meissner0749fc22002-02-05 18:11:17 +00001316 memset(&msg,0,sizeof(msg));
1317 msg.cbBuffer = buf.curoff;
1318 msg.iMethod = method;
Robert Shearmanefe606f2005-11-02 20:00:00 +00001319 hres = IRpcChannelBuffer_GetBuffer(chanbuf,&msg,&(tpinfo->iid));
Marcus Meissner0749fc22002-02-05 18:11:17 +00001320 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001321 ERR("RpcChannelBuffer GetBuffer failed, %lx\n",hres);
Robert Shearmanefe606f2005-11-02 20:00:00 +00001322 goto exit;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001323 }
1324 memcpy(msg.Buffer,buf.base,buf.curoff);
Mike Hearnd440ca42004-06-17 23:03:26 +00001325 if (relaydeb) TRACE_(olerelay)("\n");
Robert Shearmanefe606f2005-11-02 20:00:00 +00001326 hres = IRpcChannelBuffer_SendReceive(chanbuf,&msg,&status);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001327 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001328 ERR("RpcChannelBuffer SendReceive failed, %lx\n",hres);
Robert Shearmanefe606f2005-11-02 20:00:00 +00001329 goto exit;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001330 }
Mike Hearnd440ca42004-06-17 23:03:26 +00001331
Marcus Meissner89feaca2005-03-28 10:00:49 +00001332 if (relaydeb) TRACE_(olerelay)(" status = %08lx (",status);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001333 if (buf.base)
1334 buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);
1335 else
1336 buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);
1337 buf.size = msg.cbBuffer;
1338 memcpy(buf.base,msg.Buffer,buf.size);
1339 buf.curoff = 0;
Marcus Meissnere6260a32005-03-27 17:51:59 +00001340
Marcus Meissnere6260a32005-03-27 17:51:59 +00001341 /* generic deserializer using typelib description */
1342 xargs = args;
Marcus Meissner89feaca2005-03-28 10:00:49 +00001343 status = S_OK;
Marcus Meissnere6260a32005-03-27 17:51:59 +00001344 for (i=0;i<fdesc->cParams;i++) {
1345 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
Marcus Meissnere81f10c2002-06-10 02:30:20 +00001346
Marcus Meissnere6260a32005-03-27 17:51:59 +00001347 if (relaydeb) {
1348 if (i) TRACE_(olerelay)(",");
1349 if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1350 }
1351 /* No need to marshal other data than FOUT and any VT_PTR */
1352 if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {
1353 xargs += _argsize(elem->tdesc.vt);
1354 if (relaydeb) TRACE_(olerelay)("[in]");
1355 continue;
1356 }
Robert Shearman5c2a7082005-10-26 10:12:30 +00001357 hres = deserialize_param(
1358 tinfo,
1359 elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1360 relaydeb,
1361 FALSE,
1362 &(elem->tdesc),
1363 xargs,
1364 &buf
1365 );
Marcus Meissnere6260a32005-03-27 17:51:59 +00001366 if (hres) {
1367 ERR("Failed to unmarshall param, hres %lx\n",hres);
1368 status = hres;
1369 break;
1370 }
1371 xargs += _argsize(elem->tdesc.vt);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001372 }
Robert Shearman5c2a7082005-10-26 10:12:30 +00001373
Marcus Meissner89feaca2005-03-28 10:00:49 +00001374 hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));
1375 if (hres != S_OK)
Robert Shearmanefe606f2005-11-02 20:00:00 +00001376 goto exit;
Marcus Meissner89feaca2005-03-28 10:00:49 +00001377 if (relaydeb) TRACE_(olerelay)(") = %08lx\n", remoteresult);
1378
Robert Shearmanefe606f2005-11-02 20:00:00 +00001379 hres = remoteresult;
Marcus Meissner89feaca2005-03-28 10:00:49 +00001380
Robert Shearmanefe606f2005-11-02 20:00:00 +00001381exit:
Marcus Meissner0749fc22002-02-05 18:11:17 +00001382 HeapFree(GetProcessHeap(),0,buf.base);
Robert Shearmanefe606f2005-11-02 20:00:00 +00001383 IRpcChannelBuffer_Release(chanbuf);
Robert Shearmanc6296c42005-06-01 11:03:40 +00001384 ITypeInfo_Release(tinfo);
Robert Shearmanefe606f2005-11-02 20:00:00 +00001385 TRACE("-- 0x%08lx\n", hres);
1386 return hres;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001387}
1388
Alexandre Julliardcfc6c482006-06-10 11:59:33 +02001389static HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
Robert Shearmanac23f2c2005-03-11 10:18:31 +00001390{
1391 TMProxyImpl *proxy = (TMProxyImpl *)iface;
1392
1393 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1394
1395 if (proxy->outerunknown)
1396 return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);
1397
1398 FIXME("No interface\n");
1399 return E_NOINTERFACE;
1400}
1401
Alexandre Julliardcfc6c482006-06-10 11:59:33 +02001402static ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)
Robert Shearmanac23f2c2005-03-11 10:18:31 +00001403{
1404 TMProxyImpl *proxy = (TMProxyImpl *)iface;
1405
1406 TRACE("\n");
1407
1408 if (proxy->outerunknown)
1409 return IUnknown_AddRef(proxy->outerunknown);
1410
1411 return 2; /* FIXME */
1412}
1413
Alexandre Julliardcfc6c482006-06-10 11:59:33 +02001414static ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)
Robert Shearmanac23f2c2005-03-11 10:18:31 +00001415{
1416 TMProxyImpl *proxy = (TMProxyImpl *)iface;
1417
1418 TRACE("\n");
1419
1420 if (proxy->outerunknown)
1421 return IUnknown_Release(proxy->outerunknown);
1422
1423 return 1; /* FIXME */
1424}
1425
Robert Shearman5c2a7082005-10-26 10:12:30 +00001426static HRESULT WINAPI ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo)
1427{
1428 TMProxyImpl *This = (TMProxyImpl *)iface;
Robert Shearman5c2a7082005-10-26 10:12:30 +00001429
1430 TRACE("(%p)\n", pctinfo);
1431
Robert Shearmanb0218db2006-02-07 16:26:23 +01001432 return IDispatch_GetTypeInfoCount(This->dispatch, pctinfo);
Robert Shearman5c2a7082005-10-26 10:12:30 +00001433}
1434
1435static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1436{
1437 TMProxyImpl *This = (TMProxyImpl *)iface;
Robert Shearman5c2a7082005-10-26 10:12:30 +00001438
1439 TRACE("(%d, %lx, %p)\n", iTInfo, lcid, ppTInfo);
1440
Robert Shearmanb0218db2006-02-07 16:26:23 +01001441 return IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo);
Robert Shearman5c2a7082005-10-26 10:12:30 +00001442}
1443
1444static HRESULT WINAPI ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
1445{
1446 TMProxyImpl *This = (TMProxyImpl *)iface;
Robert Shearman5c2a7082005-10-26 10:12:30 +00001447
1448 TRACE("(%s, %p, %d, 0x%lx, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1449
Robert Shearmanb0218db2006-02-07 16:26:23 +01001450 return IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames,
1451 cNames, lcid, rgDispId);
Robert Shearman5c2a7082005-10-26 10:12:30 +00001452}
1453
1454static HRESULT WINAPI ProxyIDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1455 WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult,
1456 EXCEPINFO * pExcepInfo, UINT * puArgErr)
1457{
1458 TMProxyImpl *This = (TMProxyImpl *)iface;
Robert Shearman5c2a7082005-10-26 10:12:30 +00001459
Robert Shearmanb0218db2006-02-07 16:26:23 +01001460 TRACE("(%ld, %s, 0x%lx, 0x%x, %p, %p, %p, %p)\n", dispIdMember,
1461 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult,
1462 pExcepInfo, puArgErr);
Robert Shearman5c2a7082005-10-26 10:12:30 +00001463
Robert Shearmanb0218db2006-02-07 16:26:23 +01001464 return IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid,
1465 wFlags, pDispParams, pVarResult, pExcepInfo,
1466 puArgErr);
1467}
Robert Shearman5c2a7082005-10-26 10:12:30 +00001468
Robert Shearmanb0218db2006-02-07 16:26:23 +01001469static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf)
1470{
1471 HRESULT hr;
1472 CLSID clsid;
1473
1474 if ((hr = CoGetPSClsid(riid, &clsid)))
1475 return hr;
1476 return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
1477 &IID_IPSFactoryBuffer, (LPVOID*)facbuf);
Robert Shearman5c2a7082005-10-26 10:12:30 +00001478}
1479
Marcus Meissner0749fc22002-02-05 18:11:17 +00001480static HRESULT WINAPI
1481PSFacBuf_CreateProxy(
1482 LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
Robert Shearman2a54aac2004-09-07 20:42:26 +00001483 IRpcProxyBuffer **ppProxy, LPVOID *ppv)
1484{
Marcus Meissner0749fc22002-02-05 18:11:17 +00001485 HRESULT hres;
1486 ITypeInfo *tinfo;
1487 int i, nroffuncs;
Robert Shearmanb0d8e06c2005-12-06 21:24:19 +01001488 const FUNCDESC *fdesc;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001489 TMProxyImpl *proxy;
Robert Shearman5c2a7082005-10-26 10:12:30 +00001490 TYPEATTR *typeattr;
Vincent Béron9a624912002-05-31 23:06:46 +00001491
Marcus Meissner0749fc22002-02-05 18:11:17 +00001492 TRACE("(...%s...)\n",debugstr_guid(riid));
1493 hres = _get_typeinfo_for_iid(riid,&tinfo);
1494 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001495 ERR("No typeinfo for %s?\n",debugstr_guid(riid));
Marcus Meissner0749fc22002-02-05 18:11:17 +00001496 return hres;
1497 }
1498 nroffuncs = _nroffuncs(tinfo);
Robert Shearman2a54aac2004-09-07 20:42:26 +00001499 proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));
Marcus Meissner0749fc22002-02-05 18:11:17 +00001500 if (!proxy) return E_OUTOFMEMORY;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001501
1502 assert(sizeof(TMAsmProxy) == 12);
1503
Robert Shearman5c2a7082005-10-26 10:12:30 +00001504 proxy->dispatch = NULL;
Robert Shearmanb0218db2006-02-07 16:26:23 +01001505 proxy->dispatch_proxy = NULL;
Robert Shearmanac23f2c2005-03-11 10:18:31 +00001506 proxy->outerunknown = pUnkOuter;
Mike Hearn3186bd22004-06-28 23:51:24 +00001507 proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
1508 if (!proxy->asmstubs) {
1509 ERR("Could not commit pages for proxy thunks\n");
Robert Shearman2a54aac2004-09-07 20:42:26 +00001510 CoTaskMemFree(proxy);
Mike Hearn3186bd22004-06-28 23:51:24 +00001511 return E_OUTOFMEMORY;
1512 }
1513
Robert Shearman2a54aac2004-09-07 20:42:26 +00001514 InitializeCriticalSection(&proxy->crit);
1515
Marcus Meissner0749fc22002-02-05 18:11:17 +00001516 proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
1517 for (i=0;i<nroffuncs;i++) {
Marcus Meissner0749fc22002-02-05 18:11:17 +00001518 TMAsmProxy *xasm = proxy->asmstubs+i;
1519
Marcus Meissner0749fc22002-02-05 18:11:17 +00001520 switch (i) {
Robert Shearmanac23f2c2005-03-11 10:18:31 +00001521 case 0:
1522 proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001523 break;
Robert Shearmanac23f2c2005-03-11 10:18:31 +00001524 case 1:
1525 proxy->lpvtbl[i] = ProxyIUnknown_AddRef;
1526 break;
1527 case 2:
1528 proxy->lpvtbl[i] = ProxyIUnknown_Release;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001529 break;
1530 default: {
1531 int j;
Robert Shearmanac23f2c2005-03-11 10:18:31 +00001532 /* nrofargs without This */
1533 int nrofargs;
Robert Shearmanc6296c42005-06-01 11:03:40 +00001534 ITypeInfo *tinfo2;
1535 hres = _get_funcdesc(tinfo,i,&tinfo2,&fdesc,NULL,NULL);
1536 ITypeInfo_Release(tinfo2);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001537 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001538 ERR("GetFuncDesc %lx should not fail here.\n",hres);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001539 return hres;
1540 }
1541 /* some args take more than 4 byte on the stack */
1542 nrofargs = 0;
1543 for (j=0;j<fdesc->cParams;j++)
1544 nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);
1545
Pierre d'Herbemontf26e8092005-10-19 19:06:49 +00001546#ifdef __i386__
Marcus Meissner0749fc22002-02-05 18:11:17 +00001547 if (fdesc->callconv != CC_STDCALL) {
1548 ERR("calling convention is not stdcall????\n");
1549 return E_FAIL;
1550 }
Marcus Meissner0749fc22002-02-05 18:11:17 +00001551/* popl %eax - return ptr
1552 * pushl <nr>
1553 * pushl %eax
1554 * call xCall
1555 * lret <nr> (+4)
1556 *
1557 *
1558 * arg3 arg2 arg1 <method> <returnptr>
1559 */
Robert Shearmanac23f2c2005-03-11 10:18:31 +00001560 xasm->popleax = 0x58;
1561 xasm->pushlval = 0x6a;
1562 xasm->nr = i;
1563 xasm->pushleax = 0x50;
1564 xasm->lcall = 0xe8; /* relative jump */
1565 xasm->xcall = (DWORD)xCall;
1566 xasm->xcall -= (DWORD)&(xasm->lret);
1567 xasm->lret = 0xc2;
1568 xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
1569 proxy->lpvtbl[i] = xasm;
1570 break;
Pierre d'Herbemontf26e8092005-10-19 19:06:49 +00001571#else
1572 FIXME("not implemented on non i386\n");
1573 return E_FAIL;
1574#endif
Robert Shearmanac23f2c2005-03-11 10:18:31 +00001575 }
1576 }
Marcus Meissner0749fc22002-02-05 18:11:17 +00001577 }
Robert Shearman5c2a7082005-10-26 10:12:30 +00001578
1579 /* if we derive from IDispatch then defer to its proxy for its methods */
1580 hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
1581 if (hres == S_OK)
1582 {
1583 if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
1584 {
Robert Shearmanb0218db2006-02-07 16:26:23 +01001585 IPSFactoryBuffer *factory_buffer;
1586 hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
1587 if (hres == S_OK)
1588 {
1589 hres = IPSFactoryBuffer_CreateProxy(factory_buffer, NULL,
1590 &IID_IDispatch, &proxy->dispatch_proxy,
1591 (void **)&proxy->dispatch);
1592 IPSFactoryBuffer_Release(factory_buffer);
1593 }
1594 if (hres == S_OK)
1595 {
1596 proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount;
1597 proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo;
1598 proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames;
1599 proxy->lpvtbl[6] = ProxyIDispatch_Invoke;
1600 }
Robert Shearman5c2a7082005-10-26 10:12:30 +00001601 }
1602 ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
1603 }
1604
Marcus Meissner0749fc22002-02-05 18:11:17 +00001605 proxy->lpvtbl2 = &tmproxyvtable;
Robert Shearmanb3a4b592005-09-18 11:10:37 +00001606 /* one reference for the proxy */
1607 proxy->ref = 1;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001608 proxy->tinfo = tinfo;
1609 memcpy(&proxy->iid,riid,sizeof(*riid));
Bill Medland405abd52004-12-20 17:05:44 +00001610 proxy->chanbuf = 0;
Robert Shearmanb0218db2006-02-07 16:26:23 +01001611 if (hres == S_OK)
1612 {
1613 *ppv = (LPVOID)proxy;
1614 *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
1615 IUnknown_AddRef((IUnknown *)*ppv);
1616 return S_OK;
1617 }
1618 else
1619 TMProxyImpl_Release((IRpcProxyBuffer *)&proxy->lpvtbl2);
1620 return hres;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001621}
1622
1623typedef struct _TMStubImpl {
Dmitry Timoshkoveba47f12005-06-06 19:50:35 +00001624 const IRpcStubBufferVtbl *lpvtbl;
Mike McCormackfc200d02005-07-11 10:25:19 +00001625 LONG ref;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001626
1627 LPUNKNOWN pUnk;
1628 ITypeInfo *tinfo;
1629 IID iid;
Robert Shearmanb0218db2006-02-07 16:26:23 +01001630 IRpcStubBuffer *dispatch_stub;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001631} TMStubImpl;
1632
1633static HRESULT WINAPI
Robert Shearman2a54aac2004-09-07 20:42:26 +00001634TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv)
1635{
Marcus Meissner0749fc22002-02-05 18:11:17 +00001636 if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
1637 *ppv = (LPVOID)iface;
1638 IRpcStubBuffer_AddRef(iface);
1639 return S_OK;
1640 }
1641 FIXME("%s, not supported IID.\n",debugstr_guid(riid));
1642 return E_NOINTERFACE;
1643}
1644
1645static ULONG WINAPI
Robert Shearman2a54aac2004-09-07 20:42:26 +00001646TMStubImpl_AddRef(LPRPCSTUBBUFFER iface)
1647{
Alexandre Julliard241a4c32004-09-09 21:03:58 +00001648 TMStubImpl *This = (TMStubImpl *)iface;
James Hawkinsba92d292005-01-14 16:02:20 +00001649 ULONG refCount = InterlockedIncrement(&This->ref);
Mike Hearn6545d992004-07-30 18:43:27 +00001650
James Hawkinsba92d292005-01-14 16:02:20 +00001651 TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001652
James Hawkinsba92d292005-01-14 16:02:20 +00001653 return refCount;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001654}
1655
1656static ULONG WINAPI
Robert Shearman2a54aac2004-09-07 20:42:26 +00001657TMStubImpl_Release(LPRPCSTUBBUFFER iface)
1658{
Alexandre Julliard241a4c32004-09-09 21:03:58 +00001659 TMStubImpl *This = (TMStubImpl *)iface;
James Hawkinsba92d292005-01-14 16:02:20 +00001660 ULONG refCount = InterlockedDecrement(&This->ref);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001661
James Hawkinsba92d292005-01-14 16:02:20 +00001662 TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1);
Mike Hearn6545d992004-07-30 18:43:27 +00001663
James Hawkinsba92d292005-01-14 16:02:20 +00001664 if (!refCount)
Robert Shearman2a54aac2004-09-07 20:42:26 +00001665 {
1666 IRpcStubBuffer_Disconnect(iface);
Robert Shearman6bfae1a2005-07-19 20:00:07 +00001667 ITypeInfo_Release(This->tinfo);
Robert Shearman2a54aac2004-09-07 20:42:26 +00001668 CoTaskMemFree(This);
1669 }
James Hawkinsba92d292005-01-14 16:02:20 +00001670 return refCount;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001671}
1672
1673static HRESULT WINAPI
Robert Shearman2a54aac2004-09-07 20:42:26 +00001674TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer)
1675{
Alexandre Julliard241a4c32004-09-09 21:03:58 +00001676 TMStubImpl *This = (TMStubImpl *)iface;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001677
Mike Hearn6545d992004-07-30 18:43:27 +00001678 TRACE("(%p)->(%p)\n", This, pUnkServer);
1679
Marcus Meissner0749fc22002-02-05 18:11:17 +00001680 IUnknown_AddRef(pUnkServer);
1681 This->pUnk = pUnkServer;
Robert Shearmanb0218db2006-02-07 16:26:23 +01001682
1683 if (This->dispatch_stub)
1684 IRpcStubBuffer_Connect(This->dispatch_stub, pUnkServer);
1685
Marcus Meissner0749fc22002-02-05 18:11:17 +00001686 return S_OK;
1687}
1688
1689static void WINAPI
Robert Shearman2a54aac2004-09-07 20:42:26 +00001690TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)
1691{
Alexandre Julliard241a4c32004-09-09 21:03:58 +00001692 TMStubImpl *This = (TMStubImpl *)iface;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001693
Mike Hearn6545d992004-07-30 18:43:27 +00001694 TRACE("(%p)->()\n", This);
1695
Robert Shearman6bfae1a2005-07-19 20:00:07 +00001696 if (This->pUnk)
1697 {
1698 IUnknown_Release(This->pUnk);
1699 This->pUnk = NULL;
1700 }
Robert Shearmanb0218db2006-02-07 16:26:23 +01001701
1702 if (This->dispatch_stub)
1703 IRpcStubBuffer_Disconnect(This->dispatch_stub);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001704}
1705
Marcus Meissner0749fc22002-02-05 18:11:17 +00001706static HRESULT WINAPI
1707TMStubImpl_Invoke(
Robert Shearman2a54aac2004-09-07 20:42:26 +00001708 LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf)
1709{
Marcus Meissner0749fc22002-02-05 18:11:17 +00001710 int i;
Robert Shearmanb0d8e06c2005-12-06 21:24:19 +01001711 const FUNCDESC *fdesc;
Alexandre Julliard241a4c32004-09-09 21:03:58 +00001712 TMStubImpl *This = (TMStubImpl *)iface;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001713 HRESULT hres;
1714 DWORD *args, res, *xargs, nrofargs;
1715 marshal_state buf;
Mike McCormacka04b77d2005-08-08 18:38:29 +00001716 UINT nrofnames;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001717 BSTR names[10];
Robert Shearman5c2a7082005-10-26 10:12:30 +00001718 BSTR iname = NULL;
Robert Shearmanc6296c42005-06-01 11:03:40 +00001719 ITypeInfo *tinfo;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001720
Marcus Meissner0749fc22002-02-05 18:11:17 +00001721 TRACE("...\n");
Marcus Meissner0749fc22002-02-05 18:11:17 +00001722
Robert Shearman5c2a7082005-10-26 10:12:30 +00001723 if (xmsg->iMethod < 3) {
1724 ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n");
1725 return E_UNEXPECTED;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001726 }
Robert Shearman5c2a7082005-10-26 10:12:30 +00001727
Robert Shearmanb0218db2006-02-07 16:26:23 +01001728 if (This->dispatch_stub && xmsg->iMethod < sizeof(IDispatchVtbl)/sizeof(void *))
1729 return IRpcStubBuffer_Invoke(This->dispatch_stub, xmsg, rpcchanbuf);
1730
1731 memset(&buf,0,sizeof(buf));
1732 buf.size = xmsg->cbBuffer;
1733 buf.base = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer);
1734 memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer);
1735 buf.curoff = 0;
1736
Robert Shearman5c2a7082005-10-26 10:12:30 +00001737 hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001738 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001739 ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001740 return hres;
1741 }
Marcus Meissnere6260a32005-03-27 17:51:59 +00001742
Robert Shearman5c2a7082005-10-26 10:12:30 +00001743 if (iname && !lstrcmpW(iname, IDispatchW))
1744 {
1745 ERR("IDispatch cannot be marshaled by the typelib marshaler\n");
1746 ITypeInfo_Release(tinfo);
1747 return E_UNEXPECTED;
1748 }
Marcus Meissnere6260a32005-03-27 17:51:59 +00001749
1750 if (iname) SysFreeString (iname);
Marcus Meissnere6260a32005-03-27 17:51:59 +00001751
Marcus Meissner0749fc22002-02-05 18:11:17 +00001752 /* Need them for hack below */
1753 memset(names,0,sizeof(names));
Robert Shearmanc6296c42005-06-01 11:03:40 +00001754 ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001755 if (nrofnames > sizeof(names)/sizeof(names[0])) {
1756 ERR("Need more names!\n");
1757 }
1758
1759 /*dump_FUNCDESC(fdesc);*/
1760 nrofargs = 0;
1761 for (i=0;i<fdesc->cParams;i++)
1762 nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);
1763 args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
1764 if (!args) return E_OUTOFMEMORY;
1765
1766 /* Allocate all stuff used by call. */
1767 xargs = args+1;
1768 for (i=0;i<fdesc->cParams;i++) {
1769 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
1770
Robert Shearman5c2a7082005-10-26 10:12:30 +00001771 hres = deserialize_param(
1772 tinfo,
Huw Davies0c6d5462005-10-26 12:06:49 +00001773 elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
Robert Shearman5c2a7082005-10-26 10:12:30 +00001774 FALSE,
1775 TRUE,
1776 &(elem->tdesc),
1777 xargs,
1778 &buf
1779 );
Marcus Meissner0749fc22002-02-05 18:11:17 +00001780 xargs += _argsize(elem->tdesc.vt);
1781 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001782 ERR("Failed to deserialize param %s, hres %lx\n",relaystr(names[i+1]),hres);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001783 break;
1784 }
1785 }
Robert Shearman5c2a7082005-10-26 10:12:30 +00001786
Robert Shearman69562b02005-10-27 12:08:58 +00001787 args[0] = (DWORD)This->pUnk;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001788 res = _invoke(
Marcus Meissnere6260a32005-03-27 17:51:59 +00001789 (*((FARPROC**)args[0]))[fdesc->oVft/4],
1790 fdesc->callconv,
1791 (xargs-args),
1792 args
Marcus Meissner0749fc22002-02-05 18:11:17 +00001793 );
Marcus Meissner0749fc22002-02-05 18:11:17 +00001794 buf.curoff = 0;
Marcus Meissnere6260a32005-03-27 17:51:59 +00001795
Marcus Meissner0749fc22002-02-05 18:11:17 +00001796 xargs = args+1;
1797 for (i=0;i<fdesc->cParams;i++) {
1798 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
Robert Shearman5c2a7082005-10-26 10:12:30 +00001799 hres = serialize_param(
1800 tinfo,
1801 elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1802 FALSE,
1803 TRUE,
1804 &elem->tdesc,
1805 xargs,
1806 &buf
1807 );
Marcus Meissner0749fc22002-02-05 18:11:17 +00001808 xargs += _argsize(elem->tdesc.vt);
1809 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001810 ERR("Failed to stuballoc param, hres %lx\n",hres);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001811 break;
1812 }
1813 }
Robert Shearman5c2a7082005-10-26 10:12:30 +00001814
Marcus Meissner89feaca2005-03-28 10:00:49 +00001815 hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));
1816 if (hres != S_OK)
1817 return hres;
Robert Shearmanc6296c42005-06-01 11:03:40 +00001818
1819 ITypeInfo_Release(tinfo);
Robert Shearman44d6e392005-08-29 21:46:51 +00001820 HeapFree(GetProcessHeap(), 0, args);
1821
Marcus Meissner0749fc22002-02-05 18:11:17 +00001822 xmsg->cbBuffer = buf.curoff;
Robert Shearman70c34cc2006-06-09 17:25:50 +01001823 hres = IRpcChannelBuffer_GetBuffer(rpcchanbuf, xmsg, &This->iid);
1824 if (hres != S_OK)
1825 ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08lx\n", hres);
Robert Shearman44d6e392005-08-29 21:46:51 +00001826
1827 if (hres == S_OK)
1828 memcpy(xmsg->Buffer, buf.base, buf.curoff);
1829
1830 HeapFree(GetProcessHeap(), 0, buf.base);
1831
1832 TRACE("returning\n");
1833 return hres;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001834}
1835
1836static LPRPCSTUBBUFFER WINAPI
1837TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {
1838 FIXME("Huh (%s)?\n",debugstr_guid(riid));
1839 return NULL;
1840}
1841
1842static ULONG WINAPI
1843TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {
Alexandre Julliard241a4c32004-09-09 21:03:58 +00001844 TMStubImpl *This = (TMStubImpl *)iface;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001845
Robert Shearman44d6e392005-08-29 21:46:51 +00001846 FIXME("()\n");
Marcus Meissner0749fc22002-02-05 18:11:17 +00001847 return This->ref; /*FIXME? */
1848}
1849
1850static HRESULT WINAPI
1851TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {
1852 return E_NOTIMPL;
1853}
1854
1855static void WINAPI
1856TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
1857 return;
1858}
1859
Dmitry Timoshkoveba47f12005-06-06 19:50:35 +00001860static const IRpcStubBufferVtbl tmstubvtbl = {
Marcus Meissner0749fc22002-02-05 18:11:17 +00001861 TMStubImpl_QueryInterface,
1862 TMStubImpl_AddRef,
1863 TMStubImpl_Release,
1864 TMStubImpl_Connect,
1865 TMStubImpl_Disconnect,
1866 TMStubImpl_Invoke,
1867 TMStubImpl_IsIIDSupported,
1868 TMStubImpl_CountRefs,
1869 TMStubImpl_DebugServerQueryInterface,
1870 TMStubImpl_DebugServerRelease
1871};
1872
1873static HRESULT WINAPI
1874PSFacBuf_CreateStub(
1875 LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
1876 IRpcStubBuffer** ppStub
1877) {
1878 HRESULT hres;
1879 ITypeInfo *tinfo;
1880 TMStubImpl *stub;
Robert Shearmanb0218db2006-02-07 16:26:23 +01001881 TYPEATTR *typeattr;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001882
1883 TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
Robert Shearmanb0218db2006-02-07 16:26:23 +01001884
Marcus Meissner0749fc22002-02-05 18:11:17 +00001885 hres = _get_typeinfo_for_iid(riid,&tinfo);
1886 if (hres) {
Mike Hearn64eac752005-01-27 11:11:32 +00001887 ERR("No typeinfo for %s?\n",debugstr_guid(riid));
Marcus Meissner0749fc22002-02-05 18:11:17 +00001888 return hres;
1889 }
Robert Shearmanb0218db2006-02-07 16:26:23 +01001890
Robert Shearman2a54aac2004-09-07 20:42:26 +00001891 stub = CoTaskMemAlloc(sizeof(TMStubImpl));
Marcus Meissner0749fc22002-02-05 18:11:17 +00001892 if (!stub)
1893 return E_OUTOFMEMORY;
1894 stub->lpvtbl = &tmstubvtbl;
1895 stub->ref = 1;
1896 stub->tinfo = tinfo;
Robert Shearmanb0218db2006-02-07 16:26:23 +01001897 stub->dispatch_stub = NULL;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001898 memcpy(&(stub->iid),riid,sizeof(*riid));
1899 hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
1900 *ppStub = (LPRPCSTUBBUFFER)stub;
Mike Hearn6545d992004-07-30 18:43:27 +00001901 TRACE("IRpcStubBuffer: %p\n", stub);
Marcus Meissner0749fc22002-02-05 18:11:17 +00001902 if (hres)
Mike Hearn64eac752005-01-27 11:11:32 +00001903 ERR("Connect to pUnkServer failed?\n");
Robert Shearmanb0218db2006-02-07 16:26:23 +01001904
1905 /* if we derive from IDispatch then defer to its stub for some of its methods */
1906 hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
1907 if (hres == S_OK)
1908 {
1909 if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
1910 {
1911 IPSFactoryBuffer *factory_buffer;
1912 hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
1913 if (hres == S_OK)
1914 {
1915 hres = IPSFactoryBuffer_CreateStub(factory_buffer, &IID_IDispatch,
1916 pUnkServer, &stub->dispatch_stub);
1917 IPSFactoryBuffer_Release(factory_buffer);
1918 }
1919 }
1920 ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
1921 }
1922
Marcus Meissner0749fc22002-02-05 18:11:17 +00001923 return hres;
1924}
1925
Dmitry Timoshkoveba47f12005-06-06 19:50:35 +00001926static const IPSFactoryBufferVtbl psfacbufvtbl = {
Marcus Meissner0749fc22002-02-05 18:11:17 +00001927 PSFacBuf_QueryInterface,
1928 PSFacBuf_AddRef,
1929 PSFacBuf_Release,
1930 PSFacBuf_CreateProxy,
1931 PSFacBuf_CreateStub
1932};
1933
1934/* This is the whole PSFactoryBuffer object, just the vtableptr */
Dmitry Timoshkoveba47f12005-06-06 19:50:35 +00001935static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
Marcus Meissner0749fc22002-02-05 18:11:17 +00001936
1937/***********************************************************************
Alexandre Julliardb8d0f4c2005-08-09 10:38:54 +00001938 * TMARSHAL_DllGetClassObject
Marcus Meissner0749fc22002-02-05 18:11:17 +00001939 */
Alexandre Julliardb8d0f4c2005-08-09 10:38:54 +00001940HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
Marcus Meissner0749fc22002-02-05 18:11:17 +00001941{
1942 if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
1943 *ppv = &lppsfac;
1944 return S_OK;
1945 }
1946 return E_NOINTERFACE;
1947}