Removed the winedefault.reg message.
[wine] / dlls / ole32 / marshal.c
1 /*
2  *      Marshalling library
3  *
4  *  Copyright 2002  Marcus Meissner
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "objbase.h"
33 #include "ole2.h"
34 #include "ole2ver.h"
35 #include "rpc.h"
36 #include "winerror.h"
37 #include "winreg.h"
38 #include "wownt32.h"
39 #include "wtypes.h"
40 #include "wine/unicode.h"
41 #include "wine/winbase16.h"
42 #include "compobj_private.h"
43 #include "ifs.h"
44
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(ole);
48
49 extern const CLSID CLSID_DfMarshal;
50
51 /* Marshalling just passes a unique identifier to the remote client,
52  * that makes it possible to find the passed interface again.
53  *
54  * So basically we need a set of values that make it unique.
55  *
56  *      Process Identifier, Object IUnknown ptr, IID
57  *
58  * Note that the IUnknown_QI(ob,xiid,&ppv) always returns the SAME ppv value!
59  */
60
61 typedef struct _mid2unknown {
62     wine_marshal_id     mid;
63     LPUNKNOWN           pUnk;
64 } mid2unknown;
65
66 typedef struct _mid2stub {
67     wine_marshal_id     mid;
68     IRpcStubBuffer      *stub;
69     LPUNKNOWN           pUnkServer;
70 } mid2stub;
71
72 static mid2stub *stubs = NULL;
73 static int nrofstubs = 0;
74
75 static mid2unknown *proxies = NULL;
76 static int nrofproxies = 0;
77
78 HRESULT
79 MARSHAL_Find_Stub_Server(wine_marshal_id *mid,LPUNKNOWN *punk) {
80     int i;
81
82     for (i=0;i<nrofstubs;i++) {
83         if (MARSHAL_Compare_Mids_NoInterface(mid,&(stubs[i].mid))) {
84             *punk = stubs[i].pUnkServer;
85             IUnknown_AddRef((*punk));
86             return S_OK;
87         }
88     }
89     return E_FAIL;
90 }
91
92 HRESULT
93 MARSHAL_Find_Stub_Buffer(wine_marshal_id *mid,IRpcStubBuffer **stub) {
94     int i;
95
96     for (i=0;i<nrofstubs;i++) {
97         if (MARSHAL_Compare_Mids(mid,&(stubs[i].mid))) {
98             *stub = stubs[i].stub;
99             IUnknown_AddRef((*stub));
100             return S_OK;
101         }
102     }
103     return E_FAIL;
104 }
105
106 HRESULT
107 MARSHAL_Find_Stub(wine_marshal_id *mid,LPUNKNOWN *pUnk) {
108     int i;
109
110     for (i=0;i<nrofstubs;i++) {
111         if (MARSHAL_Compare_Mids(mid,&(stubs[i].mid))) {
112             *pUnk = stubs[i].pUnkServer;
113             IUnknown_AddRef((*pUnk));
114             return S_OK;
115         }
116     }
117     return E_FAIL;
118 }
119
120 HRESULT
121 MARSHAL_Register_Stub(wine_marshal_id *mid,LPUNKNOWN pUnk,IRpcStubBuffer *stub) {
122     LPUNKNOWN   xPunk;
123     if (!MARSHAL_Find_Stub(mid,&xPunk)) {
124         FIXME("Already have entry for (%lx/%s)!\n",mid->objectid,debugstr_guid(&(mid->iid)));
125         return S_OK;
126     }
127     if (nrofstubs)
128         stubs=HeapReAlloc(GetProcessHeap(),0,stubs,sizeof(stubs[0])*(nrofstubs+1));
129     else
130         stubs=HeapAlloc(GetProcessHeap(),0,sizeof(stubs[0]));
131     if (!stubs) return E_OUTOFMEMORY;
132     stubs[nrofstubs].stub = stub;
133     stubs[nrofstubs].pUnkServer = pUnk;
134     memcpy(&(stubs[nrofstubs].mid),mid,sizeof(*mid));
135     nrofstubs++;
136     return S_OK;
137 }
138
139 HRESULT
140 MARSHAL_Find_Proxy(wine_marshal_id *mid,LPUNKNOWN *punk) {
141     int i;
142
143     for (i=0;i<nrofproxies;i++)
144         if (MARSHAL_Compare_Mids(mid,&(proxies[i].mid))) {
145             *punk = proxies[i].pUnk;
146             IUnknown_AddRef((*punk));
147             return S_OK;
148         }
149     return E_FAIL;
150 }
151
152 HRESULT
153 MARSHAL_Find_Proxy_Object(wine_marshal_id *mid,LPUNKNOWN *punk) {
154     int i;
155
156     for (i=0;i<nrofproxies;i++)
157         if (MARSHAL_Compare_Mids_NoInterface(mid,&(proxies[i].mid))) {
158             *punk = proxies[i].pUnk;
159             IUnknown_AddRef((*punk));
160             return S_OK;
161         }
162     return E_FAIL;
163 }
164
165 HRESULT
166 MARSHAL_Register_Proxy(wine_marshal_id *mid,LPUNKNOWN punk) {
167     int i;
168
169     for (i=0;i<nrofproxies;i++) {
170         if (MARSHAL_Compare_Mids(mid,&(proxies[i].mid))) {
171             ERR("Already have mid?\n");
172             return E_FAIL;
173         }
174     }
175     if (nrofproxies)
176         proxies = HeapReAlloc(GetProcessHeap(),0,proxies,sizeof(proxies[0])*(nrofproxies+1));
177     else
178         proxies = HeapAlloc(GetProcessHeap(),0,sizeof(proxies[0]));
179     memcpy(&(proxies[nrofproxies].mid),mid,sizeof(*mid));
180     proxies[nrofproxies].pUnk = punk;
181     nrofproxies++;
182     IUnknown_AddRef(punk);
183     return S_OK;
184 }
185
186 /********************** StdMarshal implementation ****************************/
187 typedef struct _StdMarshalImpl {
188   ICOM_VTABLE(IMarshal) *lpvtbl;
189   DWORD                 ref;
190
191   IID                   iid;
192   DWORD                 dwDestContext;
193   LPVOID                pvDestContext;
194   DWORD                 mshlflags;
195 } StdMarshalImpl;
196
197 HRESULT WINAPI
198 StdMarshalImpl_QueryInterface(LPMARSHAL iface,REFIID riid,LPVOID *ppv) {
199   *ppv = NULL;
200   if (IsEqualIID(&IID_IUnknown,riid) || IsEqualIID(&IID_IMarshal,riid)) {
201     *ppv = iface;
202     IUnknown_AddRef(iface);
203     return S_OK;
204   }
205   FIXME("No interface for %s.\n",debugstr_guid(riid));
206   return E_NOINTERFACE;
207 }
208
209 ULONG WINAPI
210 StdMarshalImpl_AddRef(LPMARSHAL iface) {
211   ICOM_THIS(StdMarshalImpl,iface);
212   This->ref++;
213   return This->ref;
214 }
215
216 ULONG WINAPI
217 StdMarshalImpl_Release(LPMARSHAL iface) {
218   ICOM_THIS(StdMarshalImpl,iface);
219   This->ref--;
220
221   if (This->ref)
222     return This->ref;
223   HeapFree(GetProcessHeap(),0,This);
224   return 0;
225 }
226
227 HRESULT WINAPI
228 StdMarshalImpl_GetUnmarshalClass(
229   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
230   void* pvDestContext, DWORD mshlflags, CLSID* pCid
231 ) {
232   memcpy(pCid,&CLSID_DfMarshal,sizeof(CLSID_DfMarshal));
233   return S_OK;
234 }
235
236 HRESULT WINAPI
237 StdMarshalImpl_GetMarshalSizeMax(
238   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
239   void* pvDestContext, DWORD mshlflags, DWORD* pSize
240 ) {
241   *pSize = sizeof(wine_marshal_id)+sizeof(wine_marshal_data);
242   return S_OK;
243 }
244
245 HRESULT WINAPI
246 StdMarshalImpl_MarshalInterface(
247   LPMARSHAL iface, IStream *pStm,REFIID riid, void* pv, DWORD dwDestContext,
248   void* pvDestContext, DWORD mshlflags
249 ) {
250   wine_marshal_id       mid;
251   wine_marshal_data     md;
252   IUnknown              *pUnk;
253   ULONG                 res;
254   HRESULT               hres;
255   IRpcStubBuffer        *stub;
256   IPSFactoryBuffer      *psfacbuf;
257
258   TRACE("(...,%s,...)\n",debugstr_guid(riid));
259   IUnknown_QueryInterface((LPUNKNOWN)pv,&IID_IUnknown,(LPVOID*)&pUnk);
260   mid.processid = GetCurrentProcessId();
261   mid.objectid = (DWORD)pUnk; /* FIXME */
262   IUnknown_Release(pUnk);
263   memcpy(&mid.iid,riid,sizeof(mid.iid));
264   md.dwDestContext      = dwDestContext;
265   md.mshlflags          = mshlflags;
266   hres = IStream_Write(pStm,&mid,sizeof(mid),&res);
267   if (hres) return hres;
268   hres = IStream_Write(pStm,&md,sizeof(md),&res);
269   if (hres) return hres;
270
271   if (SUCCEEDED(MARSHAL_Find_Stub(&mid,&pUnk))) {
272       IUnknown_Release(pUnk);
273       return S_OK;
274   }
275   hres = get_facbuf_for_iid(riid,&psfacbuf);
276   if (hres) return hres;
277   hres = IPSFactoryBuffer_CreateStub(psfacbuf,riid,pv,&stub);
278   IPSFactoryBuffer_Release(psfacbuf);
279   if (hres) {
280     FIXME("Failed to create a stub for %s\n",debugstr_guid(riid));
281     return hres;
282   }
283   IUnknown_QueryInterface((LPUNKNOWN)pv,riid,(LPVOID*)&pUnk);
284   MARSHAL_Register_Stub(&mid,pUnk,stub);
285   IUnknown_Release(pUnk);
286   return S_OK;
287 }
288
289 HRESULT WINAPI
290 StdMarshalImpl_UnmarshalInterface(
291   LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv
292 ) {
293   wine_marshal_id       mid;
294   wine_marshal_data     md;
295   ULONG                 res;
296   HRESULT               hres;
297   IPSFactoryBuffer      *psfacbuf;
298   IRpcProxyBuffer       *rpcproxy;
299   IRpcChannelBuffer     *chanbuf;
300
301   TRACE("(...,%s,....)\n",debugstr_guid(riid));
302   hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
303   if (hres) return hres;
304   hres = IStream_Read(pStm,&md,sizeof(md),&res);
305   if (hres) return hres;
306   if (SUCCEEDED(MARSHAL_Find_Stub(&mid,(LPUNKNOWN*)ppv))) {
307       FIXME("Calling back to ourselves for %s!\n",debugstr_guid(riid));
308       return S_OK;
309   }
310   hres = get_facbuf_for_iid(riid,&psfacbuf);
311   if (hres) return hres;
312   hres = IPSFactoryBuffer_CreateProxy(psfacbuf,NULL,riid,&rpcproxy,ppv);
313   if (hres) {
314     FIXME("Failed to create a proxy for %s\n",debugstr_guid(riid));
315     return hres;
316   }
317   hres = PIPE_GetNewPipeBuf(&mid,&chanbuf);
318   IPSFactoryBuffer_Release(psfacbuf);
319   if (hres) {
320     ERR("Failed to get an rpc channel buffer for %s\n",debugstr_guid(riid));
321   } else {
322     /* Connect the channel buffer to the proxy and release the no longer
323      * needed proxy.
324      * NOTE: The proxy should have taken an extra reference because it also
325      * aggregates the object, so we can safely release our reference to it. */
326     IRpcProxyBuffer_Connect(rpcproxy,chanbuf);
327     IRpcProxyBuffer_Release(rpcproxy);
328     /* IRpcProxyBuffer takes a reference on the channel buffer and
329      * we no longer need it, so release it */
330     IRpcChannelBuffer_Release(chanbuf);
331   }
332   return hres;
333 }
334
335 HRESULT WINAPI
336 StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {
337   FIXME("(), stub!\n");
338   return S_OK;
339 }
340
341 HRESULT WINAPI
342 StdMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved) {
343   FIXME("(), stub!\n");
344   return S_OK;
345 }
346
347 ICOM_VTABLE(IMarshal) stdmvtbl = {
348     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
349     StdMarshalImpl_QueryInterface,
350     StdMarshalImpl_AddRef,
351     StdMarshalImpl_Release,
352     StdMarshalImpl_GetUnmarshalClass,
353     StdMarshalImpl_GetMarshalSizeMax,
354     StdMarshalImpl_MarshalInterface,
355     StdMarshalImpl_UnmarshalInterface,
356     StdMarshalImpl_ReleaseMarshalData,
357     StdMarshalImpl_DisconnectObject
358 };
359
360 /***********************************************************************
361  *              CoGetStandardMarshal    [OLE32.@]
362  *
363  * When the COM library in the client process receives a marshalled
364  * interface pointer, it looks for a CLSID to be used in creating a proxy
365  * for the purposes of unmarshalling the packet. If the packet does not
366  * contain a CLSID for the proxy, COM calls CoGetStandardMarshal, passing a
367  * NULL pUnk value.
368  * This function creates a standard proxy in the client process and returns
369  * a pointer to that proxy's implementation of IMarshal.
370  * COM uses this pointer to call CoUnmarshalInterface to retrieve the pointer
371  * to the requested interface.
372  */
373 HRESULT WINAPI
374 CoGetStandardMarshal(
375   REFIID riid,IUnknown *pUnk,DWORD dwDestContext,LPVOID pvDestContext,
376   DWORD mshlflags, LPMARSHAL *pMarshal
377 ) {
378   StdMarshalImpl *dm;
379
380   if (pUnk == NULL) {
381     FIXME("(%s,NULL,%lx,%p,%lx,%p), unimplemented yet.\n",
382       debugstr_guid(riid),dwDestContext,pvDestContext,mshlflags,pMarshal
383     );
384     return E_FAIL;
385   }
386   TRACE("(%s,%p,%lx,%p,%lx,%p)\n",
387     debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags,pMarshal
388   );
389   *pMarshal = HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl));
390   dm = (StdMarshalImpl*) *pMarshal;
391   if (!dm) return E_FAIL;
392   dm->lpvtbl            = &stdmvtbl;
393   dm->ref               = 1;
394
395   memcpy(&dm->iid,riid,sizeof(dm->iid));
396   dm->dwDestContext     = dwDestContext;
397   dm->pvDestContext     = pvDestContext;
398   dm->mshlflags         = mshlflags;
399   return S_OK;
400 }
401
402 /* Helper function for getting Marshaler */
403 static HRESULT WINAPI
404 _GetMarshaller(REFIID riid, IUnknown *pUnk,DWORD dwDestContext,
405   void *pvDestContext, DWORD mshlFlags, LPMARSHAL *pMarshal
406 ) {
407   HRESULT hres;
408
409   if (!pUnk)
410       return E_POINTER;
411   hres = IUnknown_QueryInterface(pUnk,&IID_IMarshal,(LPVOID*)pMarshal);
412   if (hres)
413     hres = CoGetStandardMarshal(riid,pUnk,dwDestContext,pvDestContext,mshlFlags,pMarshal);
414   return hres;
415 }
416
417 /***********************************************************************
418  *              CoGetMarshalSizeMax     [OLE32.@]
419  */
420 HRESULT WINAPI
421 CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk,
422   DWORD dwDestContext, void *pvDestContext, DWORD mshlFlags
423 ) {
424   HRESULT       hres;
425   LPMARSHAL     pMarshal;
426
427   hres = _GetMarshaller(riid,pUnk,dwDestContext,pvDestContext,mshlFlags,&pMarshal);
428   if (hres)
429     return hres;
430   hres = IMarshal_GetMarshalSizeMax(pMarshal,riid,pUnk,dwDestContext,pvDestContext,mshlFlags,pulSize);
431   *pulSize += sizeof(wine_marshal_id)+sizeof(wine_marshal_data)+sizeof(CLSID);
432   IMarshal_Release(pMarshal);
433   return hres;
434 }
435
436
437 /***********************************************************************
438  *              CoMarshalInterface      [OLE32.@]
439  */
440 HRESULT WINAPI
441 CoMarshalInterface( IStream *pStm, REFIID riid, IUnknown *pUnk,
442   DWORD dwDestContext, void *pvDestContext, DWORD mshlflags
443 ) {
444   HRESULT               hres;
445   LPMARSHAL             pMarshal;
446   CLSID                 xclsid;
447   ULONG                 writeres;
448   wine_marshal_id       mid;
449   wine_marshal_data     md;
450   ULONG                 res;
451   IUnknown              *pUnknown;
452
453   TRACE("(%p, %s, %p, %lx, %p, %lx)\n",
454     pStm,debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags
455   );
456   STUBMGR_Start(); /* Just to be sure we have one running. */
457   mid.processid = GetCurrentProcessId();
458   IUnknown_QueryInterface(pUnk,&IID_IUnknown,(LPVOID*)&pUnknown);
459   mid.objectid = (DWORD)pUnknown;
460   IUnknown_Release(pUnknown);
461   memcpy(&mid.iid,riid,sizeof(mid.iid));
462   md.dwDestContext      = dwDestContext;
463   md.mshlflags          = mshlflags;
464   hres = IStream_Write(pStm,&mid,sizeof(mid),&res);
465   if (hres) return hres;
466   hres = IStream_Write(pStm,&md,sizeof(md),&res);
467   if (hres) return hres;
468   hres = _GetMarshaller(riid,pUnk,dwDestContext,pvDestContext,mshlflags,&pMarshal);
469   if (hres) {
470     FIXME("Failed to get marshaller, %lx?\n",hres);
471     return hres;
472   }
473   hres = IMarshal_GetUnmarshalClass(pMarshal,riid,pUnk,dwDestContext,pvDestContext,mshlflags,&xclsid);
474   if (hres) {
475     FIXME("IMarshal:GetUnmarshalClass failed, %lx\n",hres);
476     goto release_marshal;
477   }
478   hres = IStream_Write(pStm,&xclsid,sizeof(xclsid),&writeres);
479   if (hres) {
480     FIXME("Stream write failed, %lx\n",hres);
481     goto release_marshal;
482   }
483   hres = IMarshal_MarshalInterface(pMarshal,pStm,riid,pUnk,dwDestContext,pvDestContext,mshlflags);
484   if (hres) {
485     if (IsEqualGUID(riid,&IID_IOleObject)) {
486       ERR("WINE currently cannot marshal IOleObject interfaces. This means you cannot embed/link OLE objects between applications.\n");
487     } else {
488       FIXME("Failed to marshal the interface %s, %lx?\n",debugstr_guid(riid),hres);
489     }
490   }
491 release_marshal:
492   IMarshal_Release(pMarshal);
493   return hres;
494 }
495
496
497 /***********************************************************************
498  *              CoUnmarshalInterface    [OLE32.@]
499  */
500 HRESULT WINAPI
501 CoUnmarshalInterface(IStream *pStm, REFIID riid, LPVOID *ppv) {
502   HRESULT               hres;
503   wine_marshal_id       mid;
504   wine_marshal_data     md;
505   ULONG                 res;
506   LPMARSHAL             pMarshal;
507   LPUNKNOWN             pUnk;
508   CLSID                 xclsid;
509
510   TRACE("(%p,%s,%p)\n",pStm,debugstr_guid(riid),ppv);
511
512   hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
513   if (hres) {
514       FIXME("Stream read 1 failed, %lx, (%ld of %d)\n",hres,res,sizeof(mid));
515       return hres;
516   }
517   hres = IStream_Read(pStm,&md,sizeof(md),&res);
518   if (hres) {
519       FIXME("Stream read 2 failed, %lx, (%ld of %d)\n",hres,res,sizeof(md));
520       return hres;
521   }
522   hres = IStream_Read(pStm,&xclsid,sizeof(xclsid),&res);
523   if (hres) {
524       FIXME("Stream read 3 failed, %lx, (%ld of %d)\n",hres,res,sizeof(xclsid));
525       return hres;
526   }
527   hres=CoCreateInstance(&xclsid,NULL,CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER,&IID_IMarshal,(void**)&pUnk);
528   if (hres) {
529       FIXME("Failed to create instance of unmarshaller %s.\n",debugstr_guid(&xclsid));
530       return hres;
531   }
532   hres = _GetMarshaller(riid,pUnk,md.dwDestContext,NULL,md.mshlflags,&pMarshal);
533   if (hres) {
534       FIXME("Failed to get unmarshaller, %lx?\n",hres);
535       return hres;
536   }
537   hres = IMarshal_UnmarshalInterface(pMarshal,pStm,riid,ppv);
538   if (hres) {
539     FIXME("Failed to Unmarshal the interface, %lx?\n",hres);
540     goto release_marshal;
541   }
542 release_marshal:
543   IMarshal_Release(pMarshal);
544   return hres;
545 }
546
547 /***********************************************************************
548  *              CoReleaseMarshalData    [OLE32.@]
549  */
550 HRESULT WINAPI
551 CoReleaseMarshalData(IStream *pStm) {
552   HRESULT               hres;
553   wine_marshal_id       mid;
554   wine_marshal_data     md;
555   ULONG                 res;
556   LPMARSHAL             pMarshal;
557   LPUNKNOWN             pUnk;
558   CLSID                 xclsid;
559
560   TRACE("(%p)\n",pStm);
561
562   hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
563   if (hres) {
564       FIXME("Stream read 1 failed, %lx, (%ld of %d)\n",hres,res,sizeof(mid));
565       return hres;
566   }
567   hres = IStream_Read(pStm,&md,sizeof(md),&res);
568   if (hres) {
569       FIXME("Stream read 2 failed, %lx, (%ld of %d)\n",hres,res,sizeof(md));
570       return hres;
571   }
572   hres = IStream_Read(pStm,&xclsid,sizeof(xclsid),&res);
573   if (hres) {
574       FIXME("Stream read 3 failed, %lx, (%ld of %d)\n",hres,res,sizeof(xclsid));
575       return hres;
576   }
577   hres=CoCreateInstance(&xclsid,NULL,CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER,&IID_IMarshal,(void**)(char*)&pUnk);
578   if (hres) {
579       FIXME("Failed to create instance of unmarshaller %s.\n",debugstr_guid(&xclsid));
580       return hres;
581   }
582   hres = IUnknown_QueryInterface(pUnk,&IID_IMarshal,(LPVOID*)(char*)&pMarshal);
583   if (hres) {
584       FIXME("Failed to get IMarshal iface, %lx?\n",hres);
585       return hres;
586   }
587   hres = IMarshal_ReleaseMarshalData(pMarshal,pStm);
588   if (hres) {
589     FIXME("Failed to releasemarshaldata the interface, %lx?\n",hres);
590   }
591   IMarshal_Release(pMarshal);
592   IUnknown_Release(pUnk);
593   return hres;
594 }
595
596
597 /***********************************************************************
598  *              CoMarshalInterThreadInterfaceInStream   [OLE32.@]
599  *
600  * Marshal an interface across threads in the same process.
601  *
602  * PARAMS
603  *  riid  [I] Identifier of the interface to be marshalled.
604  *  pUnk  [I] Pointer to IUnknown-derived interface that will be marshalled.
605  *  ppStm [O] Pointer to IStream object that is created and then used to store the marshalled inteface.
606  *
607  * RETURNS
608  *  Success: S_OK
609  *  Failure: E_OUTOFMEMORY and other COM error codes
610  *
611  * SEE
612  *   CoMarshalInterface(), CoUnmarshalInterface() and CoGetInterfaceAndReleaseStream()
613  */
614 HRESULT WINAPI
615 CoMarshalInterThreadInterfaceInStream(
616   REFIID riid, LPUNKNOWN pUnk, LPSTREAM * ppStm)
617 {
618     ULARGE_INTEGER      xpos;
619     LARGE_INTEGER               seekto;
620     HRESULT             hres;
621
622     TRACE("(%s, %p, %p)\n",debugstr_guid(riid), pUnk, ppStm);
623
624     hres = CreateStreamOnHGlobal(0, TRUE, ppStm);
625     if (FAILED(hres)) return hres;
626     hres = CoMarshalInterface(*ppStm, riid, pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
627
628     /* FIXME: is this needed? */
629     memset(&seekto,0,sizeof(seekto));
630     IStream_Seek(*ppStm,seekto,SEEK_SET,&xpos);
631
632     return hres;
633 }
634
635 /***********************************************************************
636  *              CoGetInterfaceAndReleaseStream  [OLE32.@]
637  *
638  * Unmarshalls an inteface from a stream and then releases the stream.
639  *
640  * PARAMS
641  *  pStm [I] Stream that contains the marshalled inteface.
642  *  riid [I] Interface identifier of the object to unmarshall.
643  *  ppv  [O] Address of pointer where the requested interface object will be stored.
644  *
645  * RETURNS
646  *  Success: S_OK
647  *  Failure: A COM error code
648  *
649  * SEE
650  *  CoMarshalInterThreadInterfaceInStream() and CoUnmarshalInteface()
651  */
652 HRESULT WINAPI
653 CoGetInterfaceAndReleaseStream(LPSTREAM pStm,REFIID riid, LPVOID *ppv)
654 {
655     HRESULT hres;
656
657     TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
658
659     hres = CoUnmarshalInterface(pStm, riid, ppv);
660     IStream_Release(pStm);
661     return hres;
662 }
663
664 static HRESULT WINAPI
665 SMCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) {
666   *ppv = NULL;
667   if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IClassFactory)) {
668     *ppv = (LPVOID)iface;
669     return S_OK;
670   }
671   return E_NOINTERFACE;
672 }
673 static ULONG WINAPI SMCF_AddRef(LPCLASSFACTORY iface) { return 2; }
674 static ULONG WINAPI SMCF_Release(LPCLASSFACTORY iface) { return 1; }
675
676 static HRESULT WINAPI
677 SMCF_CreateInstance(
678   LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv
679 ) {
680   if (IsEqualIID(riid,&IID_IMarshal)) {
681       StdMarshalImpl    *dm;
682       dm=(StdMarshalImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl));
683       if (!dm)
684           return E_FAIL;
685       dm->lpvtbl        = &stdmvtbl;
686       dm->ref           = 1;
687       *ppv = (LPVOID)dm;
688       return S_OK;
689   }
690   FIXME("(%s), not supported.\n",debugstr_guid(riid));
691   return E_NOINTERFACE;
692 }
693
694 static HRESULT WINAPI
695 SMCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) {
696     FIXME("(%d), stub!\n",fLock);
697     return S_OK;
698 }
699
700 static ICOM_VTABLE(IClassFactory) dfmarshalcfvtbl = {
701     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
702     SMCF_QueryInterface,
703     SMCF_AddRef,
704     SMCF_Release,
705     SMCF_CreateInstance,
706     SMCF_LockServer
707 };
708 static ICOM_VTABLE(IClassFactory) *pdfmarshalcfvtbl = &dfmarshalcfvtbl;
709
710 HRESULT
711 MARSHAL_GetStandardMarshalCF(LPVOID *ppv) {
712   *ppv = &pdfmarshalcfvtbl;
713   return S_OK;
714 }