janitorial: Remove remaining NULL checks before free() (found by Smatch).
[wine] / dlls / ole32 / tests / marshal.c
1 /*
2  * Marshaling Tests
3  *
4  * Copyright 2004 Robert Shearman
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define _WIN32_DCOM
22 #define COBJMACROS
23 #define CONST_VTABLE
24
25 #include <stdarg.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "objbase.h"
30 #include "shlguid.h"
31
32 #include "wine/test.h"
33
34 /* functions that are not present on all versions of Windows */
35 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
36
37 /* helper macros to make tests a bit leaner */
38 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %ld\n", cLocks)
39 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %ld\n", cLocks)
40 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\n", hr)
41
42 static const IID IID_IWineTest =
43 {
44     0x5201163f,
45     0x8164,
46     0x4fd0,
47     {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
48 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
49
50 static void test_cocreateinstance_proxy(void)
51 {
52     IUnknown *pProxy;
53     IMultiQI *pMQI;
54     HRESULT hr;
55
56     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
57
58     hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
59     ok_ole_success(hr, CoCreateInstance);
60     hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
61     todo_wine
62     ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
63     if (hr == S_OK)
64         IMultiQI_Release(pMQI);
65     IUnknown_Release(pProxy);
66
67     CoUninitialize();
68 }
69
70 static const LARGE_INTEGER ullZero;
71 static LONG cLocks;
72
73 static void LockModule(void)
74 {
75     InterlockedIncrement(&cLocks);
76 }
77
78 static void UnlockModule(void)
79 {
80     InterlockedDecrement(&cLocks);
81 }
82
83
84 static HRESULT WINAPI Test_IUnknown_QueryInterface(
85     LPUNKNOWN iface,
86     REFIID riid,
87     LPVOID *ppvObj)
88 {
89     if (ppvObj == NULL) return E_POINTER;
90
91     if (IsEqualGUID(riid, &IID_IUnknown))
92     {
93         *ppvObj = (LPVOID)iface;
94         IUnknown_AddRef(iface);
95         return S_OK;
96     }
97
98     *ppvObj = NULL;
99     return E_NOINTERFACE;
100 }
101
102 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
103 {
104     LockModule();
105     return 2; /* non-heap-based object */
106 }
107
108 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
109 {
110     UnlockModule();
111     return 1; /* non-heap-based object */
112 }
113
114 static const IUnknownVtbl TestUnknown_Vtbl =
115 {
116     Test_IUnknown_QueryInterface,
117     Test_IUnknown_AddRef,
118     Test_IUnknown_Release,
119 };
120
121 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
122
123
124 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
125     LPCLASSFACTORY iface,
126     REFIID riid,
127     LPVOID *ppvObj)
128 {
129     if (ppvObj == NULL) return E_POINTER;
130
131     if (IsEqualGUID(riid, &IID_IUnknown) ||
132         IsEqualGUID(riid, &IID_IClassFactory))
133     {
134         *ppvObj = (LPVOID)iface;
135         IClassFactory_AddRef(iface);
136         return S_OK;
137     }
138
139     *ppvObj = NULL;
140     return E_NOINTERFACE;
141 }
142
143 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
144 {
145     LockModule();
146     return 2; /* non-heap-based object */
147 }
148
149 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
150 {
151     UnlockModule();
152     return 1; /* non-heap-based object */
153 }
154
155 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
156     LPCLASSFACTORY iface,
157     LPUNKNOWN pUnkOuter,
158     REFIID riid,
159     LPVOID *ppvObj)
160 {
161     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
162     return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
163 }
164
165 static HRESULT WINAPI Test_IClassFactory_LockServer(
166     LPCLASSFACTORY iface,
167     BOOL fLock)
168 {
169     return S_OK;
170 }
171
172 static const IClassFactoryVtbl TestClassFactory_Vtbl =
173 {
174     Test_IClassFactory_QueryInterface,
175     Test_IClassFactory_AddRef,
176     Test_IClassFactory_Release,
177     Test_IClassFactory_CreateInstance,
178     Test_IClassFactory_LockServer
179 };
180
181 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
182
183 #define RELEASEMARSHALDATA WM_USER
184
185 struct host_object_data
186 {
187     IStream *stream;
188     IID iid;
189     IUnknown *object;
190     MSHLFLAGS marshal_flags;
191     HANDLE marshal_event;
192     IMessageFilter *filter;
193 };
194
195 static DWORD CALLBACK host_object_proc(LPVOID p)
196 {
197     struct host_object_data *data = (struct host_object_data *)p;
198     HRESULT hr;
199     MSG msg;
200
201     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
202
203     if (data->filter)
204     {
205         IMessageFilter * prev_filter = NULL;
206         hr = CoRegisterMessageFilter(data->filter, &prev_filter);
207         if (prev_filter) IMessageFilter_Release(prev_filter);
208         ok_ole_success(hr, CoRegisterMessageFilter);
209     }
210
211     hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
212     ok_ole_success(hr, CoMarshalInterface);
213
214     /* force the message queue to be created before signaling parent thread */
215     PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
216
217     SetEvent(data->marshal_event);
218
219     while (GetMessage(&msg, NULL, 0, 0))
220     {
221         if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
222         {
223             trace("releasing marshal data\n");
224             CoReleaseMarshalData(data->stream);
225             SetEvent((HANDLE)msg.lParam);
226         }
227         else
228             DispatchMessage(&msg);
229     }
230
231     HeapFree(GetProcessHeap(), 0, data);
232
233     CoUninitialize();
234
235     return hr;
236 }
237
238 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
239 {
240     DWORD tid = 0;
241     HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
242     struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
243
244     data->stream = stream;
245     data->iid = *riid;
246     data->object = object;
247     data->marshal_flags = marshal_flags;
248     data->marshal_event = marshal_event;
249     data->filter = filter;
250
251     *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
252
253     /* wait for marshaling to complete before returning */
254     WaitForSingleObject(marshal_event, INFINITE);
255     CloseHandle(marshal_event);
256
257     return tid;
258 }
259
260 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
261 {
262     return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
263 }
264
265 /* asks thread to release the marshal data because it has to be done by the
266  * same thread that marshaled the interface in the first place. */
267 static void release_host_object(DWORD tid)
268 {
269     HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
270     PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
271     WaitForSingleObject(event, INFINITE);
272     CloseHandle(event);
273 }
274
275 static void end_host_object(DWORD tid, HANDLE thread)
276 {
277     BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
278     ok(ret, "PostThreadMessage failed with error %ld\n", GetLastError());
279     /* be careful of races - don't return until hosting thread has terminated */
280     WaitForSingleObject(thread, INFINITE);
281     CloseHandle(thread);
282 }
283
284 /* tests failure case of interface not having a marshaler specified in the
285  * registry */
286 static void test_no_marshaler(void)
287 {
288     IStream *pStream;
289     HRESULT hr;
290
291     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
292     ok_ole_success(hr, CreateStreamOnHGlobal);
293     hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
294     ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08lx\n", hr);
295
296     IStream_Release(pStream);
297 }
298
299 /* tests normal marshal and then release without unmarshaling */
300 static void test_normal_marshal_and_release(void)
301 {
302     HRESULT hr;
303     IStream *pStream = NULL;
304
305     cLocks = 0;
306
307     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
308     ok_ole_success(hr, CreateStreamOnHGlobal);
309     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
310     ok_ole_success(hr, CoMarshalInterface);
311
312     ok_more_than_one_lock();
313
314     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
315     hr = CoReleaseMarshalData(pStream);
316     ok_ole_success(hr, CoReleaseMarshalData);
317     IStream_Release(pStream);
318
319     ok_no_locks();
320 }
321
322 /* tests success case of a same-thread marshal and unmarshal */
323 static void test_normal_marshal_and_unmarshal(void)
324 {
325     HRESULT hr;
326     IStream *pStream = NULL;
327     IUnknown *pProxy = NULL;
328
329     cLocks = 0;
330
331     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
332     ok_ole_success(hr, CreateStreamOnHGlobal);
333     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
334     ok_ole_success(hr, CoMarshalInterface);
335
336     ok_more_than_one_lock();
337     
338     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
339     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
340     ok_ole_success(hr, CoUnmarshalInterface);
341     IStream_Release(pStream);
342
343     ok_more_than_one_lock();
344
345     IUnknown_Release(pProxy);
346
347     ok_no_locks();
348 }
349
350 /* tests failure case of unmarshaling a freed object */
351 static void test_marshal_and_unmarshal_invalid(void)
352 {
353     HRESULT hr;
354     IStream *pStream = NULL;
355     IClassFactory *pProxy = NULL;
356     DWORD tid;
357     void * dummy;
358     HANDLE thread;
359
360     cLocks = 0;
361
362     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
363     ok_ole_success(hr, CreateStreamOnHGlobal);
364     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
365
366     ok_more_than_one_lock();
367         
368     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
369     hr = CoReleaseMarshalData(pStream);
370     ok_ole_success(hr, CoReleaseMarshalData);
371
372     ok_no_locks();
373
374     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
375     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
376     todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
377
378     ok_no_locks();
379
380     if (pProxy)
381     {
382         hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
383         ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08lx\n", hr);
384
385         IClassFactory_Release(pProxy);
386     }
387
388     IStream_Release(pStream);
389
390     end_host_object(tid, thread);
391 }
392
393 /* tests success case of an interthread marshal */
394 static void test_interthread_marshal_and_unmarshal(void)
395 {
396     HRESULT hr;
397     IStream *pStream = NULL;
398     IUnknown *pProxy = NULL;
399     DWORD tid;
400     HANDLE thread;
401
402     cLocks = 0;
403
404     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
405     ok_ole_success(hr, CreateStreamOnHGlobal);
406     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
407
408     ok_more_than_one_lock();
409     
410     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
411     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
412     ok_ole_success(hr, CoUnmarshalInterface);
413     IStream_Release(pStream);
414
415     ok_more_than_one_lock();
416
417     IUnknown_Release(pProxy);
418
419     ok_no_locks();
420
421     end_host_object(tid, thread);
422 }
423
424 /* the number of external references that Wine's proxy manager normally gives
425  * out, so we can test the border case of running out of references */
426 #define NORMALEXTREFS 5
427
428 /* tests success case of an interthread marshal and then marshaling the proxy */
429 static void test_proxy_marshal_and_unmarshal(void)
430 {
431     HRESULT hr;
432     IStream *pStream = NULL;
433     IUnknown *pProxy = NULL;
434     IUnknown *pProxy2 = NULL;
435     DWORD tid;
436     HANDLE thread;
437     int i;
438
439     cLocks = 0;
440
441     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
442     ok_ole_success(hr, CreateStreamOnHGlobal);
443     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
444
445     ok_more_than_one_lock();
446     
447     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
448     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
449     ok_ole_success(hr, CoUnmarshalInterface);
450
451     ok_more_than_one_lock();
452
453     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
454     /* marshal the proxy */
455     hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
456     ok_ole_success(hr, CoMarshalInterface);
457
458     ok_more_than_one_lock();
459
460     /* marshal 5 more times to exhaust the normal external references of 5 */
461     for (i = 0; i < NORMALEXTREFS; i++)
462     {
463         hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
464         ok_ole_success(hr, CoMarshalInterface);
465     }
466
467     ok_more_than_one_lock();
468
469     /* release the original proxy to test that we successfully keep the
470      * original object alive */
471     IUnknown_Release(pProxy);
472
473     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
474     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
475     ok_ole_success(hr, CoUnmarshalInterface);
476
477     ok_more_than_one_lock();
478
479     /* now the proxies should be as follows:
480      *  pProxy2 -> &Test_ClassFactory
481      * they should NOT be as follows:
482      *  pProxy -> &Test_ClassFactory
483      *  pProxy2 -> pProxy
484      * the above can only really be tested by looking in +ole traces
485      */
486
487     IUnknown_Release(pProxy2);
488
489     /* unmarshal all of the proxies to check that the object stub still exists */
490     for (i = 0; i < NORMALEXTREFS; i++)
491     {
492         hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
493         ok_ole_success(hr, CoUnmarshalInterface);
494
495         IUnknown_Release(pProxy2);
496     }
497
498     ok_no_locks();
499
500     IStream_Release(pStream);
501
502     end_host_object(tid, thread);
503 }
504
505 /* tests success case of an interthread marshal and then marshaling the proxy
506  * using an iid that hasn't previously been unmarshaled */
507 static void test_proxy_marshal_and_unmarshal2(void)
508 {
509     HRESULT hr;
510     IStream *pStream = NULL;
511     IUnknown *pProxy = NULL;
512     IUnknown *pProxy2 = NULL;
513     DWORD tid;
514     HANDLE thread;
515
516     cLocks = 0;
517
518     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
519     ok_ole_success(hr, CreateStreamOnHGlobal);
520     tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
521
522     ok_more_than_one_lock();
523
524     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
525     hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
526     ok_ole_success(hr, CoUnmarshalInterface);
527
528     ok_more_than_one_lock();
529
530     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
531     /* marshal the proxy */
532     hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
533     ok_ole_success(hr, CoMarshalInterface);
534
535     ok_more_than_one_lock();
536
537     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
538     /* unmarshal the second proxy to the object */
539     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
540     ok_ole_success(hr, CoUnmarshalInterface);
541     IStream_Release(pStream);
542
543     /* now the proxies should be as follows:
544      *  pProxy -> &Test_ClassFactory
545      *  pProxy2 -> &Test_ClassFactory
546      * they should NOT be as follows:
547      *  pProxy -> &Test_ClassFactory
548      *  pProxy2 -> pProxy
549      * the above can only really be tested by looking in +ole traces
550      */
551
552     ok_more_than_one_lock();
553
554     IUnknown_Release(pProxy);
555
556     ok_more_than_one_lock();
557
558     IUnknown_Release(pProxy2);
559
560     ok_no_locks();
561
562     end_host_object(tid, thread);
563 }
564
565 /* tests that stubs are released when the containing apartment is destroyed */
566 static void test_marshal_stub_apartment_shutdown(void)
567 {
568     HRESULT hr;
569     IStream *pStream = NULL;
570     IUnknown *pProxy = NULL;
571     DWORD tid;
572     HANDLE thread;
573
574     cLocks = 0;
575
576     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
577     ok_ole_success(hr, CreateStreamOnHGlobal);
578     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
579
580     ok_more_than_one_lock();
581     
582     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
583     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
584     ok_ole_success(hr, CoUnmarshalInterface);
585     IStream_Release(pStream);
586
587     ok_more_than_one_lock();
588
589     end_host_object(tid, thread);
590
591     ok_no_locks();
592
593     IUnknown_Release(pProxy);
594
595     ok_no_locks();
596 }
597
598 /* tests that proxies are released when the containing apartment is destroyed */
599 static void test_marshal_proxy_apartment_shutdown(void)
600 {
601     HRESULT hr;
602     IStream *pStream = NULL;
603     IUnknown *pProxy = NULL;
604     DWORD tid;
605     HANDLE thread;
606
607     cLocks = 0;
608
609     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
610     ok_ole_success(hr, CreateStreamOnHGlobal);
611     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
612
613     ok_more_than_one_lock();
614     
615     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
616     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
617     ok_ole_success(hr, CoUnmarshalInterface);
618     IStream_Release(pStream);
619
620     ok_more_than_one_lock();
621
622     CoUninitialize();
623
624     ok_no_locks();
625
626     IUnknown_Release(pProxy);
627
628     ok_no_locks();
629
630     end_host_object(tid, thread);
631
632     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
633 }
634
635 /* tests that proxies are released when the containing mta apartment is destroyed */
636 static void test_marshal_proxy_mta_apartment_shutdown(void)
637 {
638     HRESULT hr;
639     IStream *pStream = NULL;
640     IUnknown *pProxy = NULL;
641     DWORD tid;
642     HANDLE thread;
643
644     CoUninitialize();
645     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
646
647     cLocks = 0;
648
649     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
650     ok_ole_success(hr, CreateStreamOnHGlobal);
651     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
652
653     ok_more_than_one_lock();
654
655     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
656     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
657     ok_ole_success(hr, CoUnmarshalInterface);
658     IStream_Release(pStream);
659
660     ok_more_than_one_lock();
661
662     CoUninitialize();
663
664     ok_no_locks();
665
666     IUnknown_Release(pProxy);
667
668     ok_no_locks();
669
670     end_host_object(tid, thread);
671
672     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
673 }
674
675 struct ncu_params
676 {
677     LPSTREAM stream;
678     HANDLE marshal_event;
679     HANDLE unmarshal_event;
680 };
681
682 /* helper for test_no_couninitialize_server */
683 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
684 {
685     struct ncu_params *ncu_params = (struct ncu_params *)p;
686     HRESULT hr;
687
688     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
689
690     hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
691     ok_ole_success(hr, CoMarshalInterface);
692
693     SetEvent(ncu_params->marshal_event);
694
695     WaitForSingleObject(ncu_params->unmarshal_event, INFINITE);
696
697     /* die without calling CoUninitialize */
698
699     return 0;
700 }
701
702 /* tests apartment that an apartment with a stub is released without deadlock
703  * if the owning thread exits */
704 static void test_no_couninitialize_server(void)
705 {
706     HRESULT hr;
707     IStream *pStream = NULL;
708     IUnknown *pProxy = NULL;
709     DWORD tid;
710     HANDLE thread;
711     struct ncu_params ncu_params;
712
713     cLocks = 0;
714
715     ncu_params.marshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
716     ncu_params.unmarshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
717
718     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
719     ok_ole_success(hr, CreateStreamOnHGlobal);
720     ncu_params.stream = pStream;
721
722     thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
723
724     WaitForSingleObject(ncu_params.marshal_event, INFINITE);
725     ok_more_than_one_lock();
726
727     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
728     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
729     ok_ole_success(hr, CoUnmarshalInterface);
730     IStream_Release(pStream);
731
732     ok_more_than_one_lock();
733
734     SetEvent(ncu_params.unmarshal_event);
735     WaitForSingleObject(thread, INFINITE);
736
737     ok_no_locks();
738
739     CloseHandle(thread);
740     CloseHandle(ncu_params.marshal_event);
741     CloseHandle(ncu_params.unmarshal_event);
742
743     IUnknown_Release(pProxy);
744
745     ok_no_locks();
746 }
747
748 /* STA -> STA call during DLL_THREAD_DETACH */
749 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
750 {
751     struct ncu_params *ncu_params = (struct ncu_params *)p;
752     HRESULT hr;
753     IUnknown *pProxy = NULL;
754
755     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
756
757     hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
758     ok_ole_success(hr, CoUnmarshalInterface);
759
760     ok_more_than_one_lock();
761
762     /* die without calling CoUninitialize */
763
764     return 0;
765 }
766
767 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
768 static void test_no_couninitialize_client(void)
769 {
770     HRESULT hr;
771     IStream *pStream = NULL;
772     DWORD tid;
773     DWORD host_tid;
774     HANDLE thread;
775     HANDLE host_thread;
776     struct ncu_params ncu_params;
777
778     cLocks = 0;
779
780     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
781     ok_ole_success(hr, CreateStreamOnHGlobal);
782     ncu_params.stream = pStream;
783
784     /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
785      * always deadlock when called from within DllMain */
786     host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
787     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
788
789     ok_more_than_one_lock();
790
791     thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
792
793     WaitForSingleObject(thread, INFINITE);
794     CloseHandle(thread);
795
796     ok_no_locks();
797
798     end_host_object(host_tid, host_thread);
799 }
800
801 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
802 static void test_tableweak_marshal_and_unmarshal_twice(void)
803 {
804     HRESULT hr;
805     IStream *pStream = NULL;
806     IUnknown *pProxy1 = NULL;
807     IUnknown *pProxy2 = NULL;
808     DWORD tid;
809     HANDLE thread;
810
811     cLocks = 0;
812
813     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
814     ok_ole_success(hr, CreateStreamOnHGlobal);
815     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
816
817     ok_more_than_one_lock();
818
819     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
820     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
821     ok_ole_success(hr, CoUnmarshalInterface);
822
823     ok_more_than_one_lock();
824
825     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
826     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
827     ok_ole_success(hr, CoUnmarshalInterface);
828
829     ok_more_than_one_lock();
830
831     IUnknown_Release(pProxy1);
832     IUnknown_Release(pProxy2);
833
834     /* this line is shows the difference between weak and strong table marshaling:
835      *  weak has cLocks == 0
836      *  strong has cLocks > 0 */
837     ok_no_locks();
838
839     end_host_object(tid, thread);
840 }
841
842 /* tests releasing after unmarshaling one object */
843 static void test_tableweak_marshal_releasedata1(void)
844 {
845     HRESULT hr;
846     IStream *pStream = NULL;
847     IUnknown *pProxy1 = NULL;
848     IUnknown *pProxy2 = NULL;
849     DWORD tid;
850     HANDLE thread;
851
852     cLocks = 0;
853
854     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
855     ok_ole_success(hr, CreateStreamOnHGlobal);
856     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
857
858     ok_more_than_one_lock();
859
860     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
861     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
862     ok_ole_success(hr, CoUnmarshalInterface);
863
864     ok_more_than_one_lock();
865
866     /* release the remaining reference on the object by calling
867      * CoReleaseMarshalData in the hosting thread */
868     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
869     release_host_object(tid);
870
871     ok_more_than_one_lock();
872
873     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
874     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
875     ok_ole_success(hr, CoUnmarshalInterface);
876     IStream_Release(pStream);
877
878     ok_more_than_one_lock();
879
880     IUnknown_Release(pProxy1);
881     if (pProxy2)
882         IUnknown_Release(pProxy2);
883
884     /* this line is shows the difference between weak and strong table marshaling:
885      *  weak has cLocks == 0
886      *  strong has cLocks > 0 */
887     ok_no_locks();
888
889     end_host_object(tid, thread);
890 }
891
892 /* tests releasing after unmarshaling one object */
893 static void test_tableweak_marshal_releasedata2(void)
894 {
895     HRESULT hr;
896     IStream *pStream = NULL;
897     IUnknown *pProxy = NULL;
898     DWORD tid;
899     HANDLE thread;
900
901     cLocks = 0;
902
903     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
904     ok_ole_success(hr, CreateStreamOnHGlobal);
905     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
906
907     ok_more_than_one_lock();
908
909     /* release the remaining reference on the object by calling
910      * CoReleaseMarshalData in the hosting thread */
911     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
912     release_host_object(tid);
913
914     ok_no_locks();
915
916     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
917     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
918     todo_wine
919     {
920     ok(hr == CO_E_OBJNOTREG,
921        "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08lx instead\n",
922        hr);
923     }
924     IStream_Release(pStream);
925
926     ok_no_locks();
927
928     end_host_object(tid, thread);
929 }
930
931 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
932 static void test_tablestrong_marshal_and_unmarshal_twice(void)
933 {
934     HRESULT hr;
935     IStream *pStream = NULL;
936     IUnknown *pProxy1 = NULL;
937     IUnknown *pProxy2 = NULL;
938     DWORD tid;
939     HANDLE thread;
940
941     cLocks = 0;
942
943     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
944     ok_ole_success(hr, CreateStreamOnHGlobal);
945     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
946
947     ok_more_than_one_lock();
948
949     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
950     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
951     ok_ole_success(hr, CoUnmarshalInterface);
952
953     ok_more_than_one_lock();
954
955     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
956     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
957     ok_ole_success(hr, CoUnmarshalInterface);
958
959     ok_more_than_one_lock();
960
961     if (pProxy1) IUnknown_Release(pProxy1);
962     if (pProxy2) IUnknown_Release(pProxy2);
963
964     /* this line is shows the difference between weak and strong table marshaling:
965      *  weak has cLocks == 0
966      *  strong has cLocks > 0 */
967     ok_more_than_one_lock();
968
969     /* release the remaining reference on the object by calling
970      * CoReleaseMarshalData in the hosting thread */
971     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
972     release_host_object(tid);
973     IStream_Release(pStream);
974
975     ok_no_locks();
976
977     end_host_object(tid, thread);
978 }
979
980 /* tests CoLockObjectExternal */
981 static void test_lock_object_external(void)
982 {
983     HRESULT hr;
984     IStream *pStream = NULL;
985
986     cLocks = 0;
987
988     /* test the stub manager creation aspect of CoLockObjectExternal when the
989      * object hasn't been marshaled yet */
990     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
991
992     ok_more_than_one_lock();
993
994     CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
995
996     ok_no_locks();
997
998     /* test our empty stub manager being handled correctly in
999      * CoMarshalInterface */
1000     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1001
1002     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1003     ok_ole_success(hr, CreateStreamOnHGlobal);
1004     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1005     ok_ole_success(hr, CoMarshalInterface);
1006
1007     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1008
1009     ok_more_than_one_lock();
1010
1011     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1012     hr = CoReleaseMarshalData(pStream);
1013     ok_ole_success(hr, CoReleaseMarshalData);
1014     IStream_Release(pStream);
1015
1016     ok_more_than_one_lock();
1017
1018     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1019
1020     ok_more_than_one_lock();
1021
1022     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1023
1024     ok_no_locks();
1025 }
1026
1027 /* tests disconnecting stubs */
1028 static void test_disconnect_stub(void)
1029 {
1030     HRESULT hr;
1031     IStream *pStream = NULL;
1032
1033     cLocks = 0;
1034
1035     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1036     ok_ole_success(hr, CreateStreamOnHGlobal);
1037     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1038     ok_ole_success(hr, CoMarshalInterface);
1039
1040     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1041
1042     ok_more_than_one_lock();
1043     
1044     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1045     hr = CoReleaseMarshalData(pStream);
1046     ok_ole_success(hr, CoReleaseMarshalData);
1047     IStream_Release(pStream);
1048
1049     ok_more_than_one_lock();
1050
1051     CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1052
1053     ok_no_locks();
1054 }
1055
1056 /* tests failure case of a same-thread marshal and unmarshal twice */
1057 static void test_normal_marshal_and_unmarshal_twice(void)
1058 {
1059     HRESULT hr;
1060     IStream *pStream = NULL;
1061     IUnknown *pProxy1 = NULL;
1062     IUnknown *pProxy2 = NULL;
1063
1064     cLocks = 0;
1065
1066     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1067     ok_ole_success(hr, CreateStreamOnHGlobal);
1068     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1069     ok_ole_success(hr, CoMarshalInterface);
1070
1071     ok_more_than_one_lock();
1072     
1073     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1074     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1075     ok_ole_success(hr, CoUnmarshalInterface);
1076
1077     ok_more_than_one_lock();
1078
1079     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1080     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1081     ok(hr == CO_E_OBJNOTCONNECTED,
1082         "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08lx\n", hr);
1083
1084     IStream_Release(pStream);
1085
1086     ok_more_than_one_lock();
1087
1088     IUnknown_Release(pProxy1);
1089
1090     ok_no_locks();
1091 }
1092
1093 /* tests success case of marshaling and unmarshaling an HRESULT */
1094 static void test_hresult_marshaling(void)
1095 {
1096     HRESULT hr;
1097     HRESULT hr_marshaled = 0;
1098     IStream *pStream = NULL;
1099     static const HRESULT E_DEADBEEF = 0xdeadbeef;
1100
1101     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1102     ok_ole_success(hr, CreateStreamOnHGlobal);
1103
1104     hr = CoMarshalHresult(pStream, E_DEADBEEF);
1105     ok_ole_success(hr, CoMarshalHresult);
1106
1107     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1108     hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1109     ok_ole_success(hr, IStream_Read);
1110
1111     ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
1112
1113     hr_marshaled = 0;
1114     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1115     hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1116     ok_ole_success(hr, CoUnmarshalHresult);
1117
1118     ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
1119
1120     IStream_Release(pStream);
1121 }
1122
1123
1124 /* helper for test_proxy_used_in_wrong_thread */
1125 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1126 {
1127     IClassFactory * cf = (IClassFactory *)p;
1128     HRESULT hr;
1129     IUnknown * proxy = NULL;
1130
1131     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1132
1133     hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1134     if (proxy) IUnknown_Release(proxy);
1135     ok(hr == RPC_E_WRONG_THREAD,
1136         "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08lx\n",
1137         hr);
1138
1139     CoUninitialize();
1140
1141     return 0;
1142 }
1143
1144 /* tests failure case of a using a proxy in the wrong apartment */
1145 static void test_proxy_used_in_wrong_thread(void)
1146 {
1147     HRESULT hr;
1148     IStream *pStream = NULL;
1149     IUnknown *pProxy = NULL;
1150     DWORD tid, tid2;
1151     HANDLE thread;
1152     HANDLE host_thread;
1153
1154     cLocks = 0;
1155
1156     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1157     ok_ole_success(hr, CreateStreamOnHGlobal);
1158     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1159
1160     ok_more_than_one_lock();
1161     
1162     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1163     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1164     ok_ole_success(hr, CoUnmarshalInterface);
1165     IStream_Release(pStream);
1166
1167     ok_more_than_one_lock();
1168
1169     /* create a thread that we can misbehave in */
1170     thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1171
1172     WaitForSingleObject(thread, INFINITE);
1173     CloseHandle(thread);
1174
1175     IUnknown_Release(pProxy);
1176
1177     ok_no_locks();
1178
1179     end_host_object(tid, host_thread);
1180 }
1181
1182 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1183 {
1184     if (ppvObj == NULL) return E_POINTER;
1185
1186     if (IsEqualGUID(riid, &IID_IUnknown) ||
1187         IsEqualGUID(riid, &IID_IClassFactory))
1188     {
1189         *ppvObj = (LPVOID)iface;
1190         IClassFactory_AddRef(iface);
1191         return S_OK;
1192     }
1193
1194     return E_NOINTERFACE;
1195 }
1196
1197 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1198 {
1199     return 2; /* non-heap object */
1200 }
1201
1202 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1203 {
1204     return 1; /* non-heap object */
1205 }
1206
1207 static DWORD WINAPI MessageFilter_HandleInComingCall(
1208   IMessageFilter *iface,
1209   DWORD dwCallType,
1210   HTASK threadIDCaller,
1211   DWORD dwTickCount,
1212   LPINTERFACEINFO lpInterfaceInfo)
1213 {
1214     static int callcount = 0;
1215     DWORD ret;
1216     trace("HandleInComingCall\n");
1217     switch (callcount)
1218     {
1219     case 0:
1220         ret = SERVERCALL_REJECTED;
1221         break;
1222     case 1:
1223         ret = SERVERCALL_RETRYLATER;
1224         break;
1225     default:
1226         ret = SERVERCALL_ISHANDLED;
1227         break;
1228     }
1229     callcount++;
1230     return ret;
1231 }
1232
1233 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1234   IMessageFilter *iface,
1235   HTASK threadIDCallee,
1236   DWORD dwTickCount,
1237   DWORD dwRejectType)
1238 {
1239     trace("RetryRejectedCall\n");
1240     return 0;
1241 }
1242
1243 static DWORD WINAPI MessageFilter_MessagePending(
1244   IMessageFilter *iface,
1245   HTASK threadIDCallee,
1246   DWORD dwTickCount,
1247   DWORD dwPendingType)
1248 {
1249     trace("MessagePending\n");
1250     return PENDINGMSG_WAITNOPROCESS;
1251 }
1252
1253 static const IMessageFilterVtbl MessageFilter_Vtbl =
1254 {
1255     MessageFilter_QueryInterface,
1256     MessageFilter_AddRef,
1257     MessageFilter_Release,
1258     MessageFilter_HandleInComingCall,
1259     MessageFilter_RetryRejectedCall,
1260     MessageFilter_MessagePending
1261 };
1262
1263 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1264
1265 static void test_message_filter(void)
1266 {
1267     HRESULT hr;
1268     IStream *pStream = NULL;
1269     IClassFactory *cf = NULL;
1270     DWORD tid;
1271     IUnknown *proxy = NULL;
1272     IMessageFilter *prev_filter = NULL;
1273     HANDLE thread;
1274
1275     cLocks = 0;
1276
1277     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1278     ok_ole_success(hr, CreateStreamOnHGlobal);
1279     tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1280
1281     ok_more_than_one_lock();
1282
1283     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1284     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1285     ok_ole_success(hr, CoUnmarshalInterface);
1286     IStream_Release(pStream);
1287
1288     ok_more_than_one_lock();
1289
1290     hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1291     todo_wine { ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08lx instead\n", hr); }
1292     if (proxy) IUnknown_Release(proxy);
1293     proxy = NULL;
1294
1295     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1296     ok_ole_success(hr, CoRegisterMessageFilter);
1297     if (prev_filter) IMessageFilter_Release(prev_filter);
1298
1299     hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1300     ok_ole_success(hr, IClassFactory_CreateInstance);
1301
1302     IUnknown_Release(proxy);
1303
1304     IClassFactory_Release(cf);
1305
1306     ok_no_locks();
1307
1308     end_host_object(tid, thread);
1309 }
1310
1311 /* test failure case of trying to unmarshal from bad stream */
1312 static void test_bad_marshal_stream(void)
1313 {
1314     HRESULT hr;
1315     IStream *pStream = NULL;
1316
1317     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1318     ok_ole_success(hr, CreateStreamOnHGlobal);
1319     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1320     ok_ole_success(hr, CoMarshalInterface);
1321
1322     ok_more_than_one_lock();
1323
1324     /* try to read beyond end of stream */
1325     hr = CoReleaseMarshalData(pStream);
1326     ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08lx instead\n", hr);
1327
1328     /* now release for real */
1329     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1330     hr = CoReleaseMarshalData(pStream);
1331     ok_ole_success(hr, CoReleaseMarshalData);
1332
1333     IStream_Release(pStream);
1334 }
1335
1336 /* tests that proxies implement certain interfaces */
1337 static void test_proxy_interfaces(void)
1338 {
1339     HRESULT hr;
1340     IStream *pStream = NULL;
1341     IUnknown *pProxy = NULL;
1342     IUnknown *pOtherUnknown = NULL;
1343     DWORD tid;
1344     HANDLE thread;
1345
1346     cLocks = 0;
1347
1348     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1349     ok_ole_success(hr, CreateStreamOnHGlobal);
1350     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1351
1352     ok_more_than_one_lock();
1353         
1354     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1355     hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1356     ok_ole_success(hr, CoUnmarshalInterface);
1357     IStream_Release(pStream);
1358
1359     ok_more_than_one_lock();
1360
1361     hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1362     ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1363     if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1364
1365     hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1366     todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); }
1367     if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1368
1369     hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1370     ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1371     if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1372
1373     hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1374     ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1375     if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1376
1377     /* IMarshal2 is also supported on NT-based systems, but is pretty much
1378      * useless as it has no more methods over IMarshal that it inherits from. */
1379
1380     IUnknown_Release(pProxy);
1381
1382     ok_no_locks();
1383
1384     end_host_object(tid, thread);
1385 }
1386
1387 typedef struct
1388 {
1389     const IUnknownVtbl *lpVtbl;
1390     ULONG refs;
1391 } HeapUnknown;
1392
1393 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1394 {
1395     if (IsEqualIID(riid, &IID_IUnknown))
1396     {
1397         IUnknown_AddRef(iface);
1398         *ppv = (LPVOID)iface;
1399         return S_OK;
1400     }
1401     *ppv = NULL;
1402     return E_NOINTERFACE;
1403 }
1404
1405 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1406 {
1407     HeapUnknown *This = (HeapUnknown *)iface;
1408     trace("HeapUnknown_AddRef(%p)\n", iface);
1409     return InterlockedIncrement((LONG*)&This->refs);
1410 }
1411
1412 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1413 {
1414     HeapUnknown *This = (HeapUnknown *)iface;
1415     ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1416     trace("HeapUnknown_Release(%p)\n", iface);
1417     if (!refs) HeapFree(GetProcessHeap(), 0, This);
1418     return refs;
1419 }
1420
1421 static const IUnknownVtbl HeapUnknown_Vtbl =
1422 {
1423     HeapUnknown_QueryInterface,
1424     HeapUnknown_AddRef,
1425     HeapUnknown_Release
1426 };
1427
1428 static void test_proxybuffer(REFIID riid)
1429 {
1430     HRESULT hr;
1431     IPSFactoryBuffer *psfb;
1432     IRpcProxyBuffer *proxy;
1433     LPVOID lpvtbl;
1434     ULONG refs;
1435     CLSID clsid;
1436     HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1437
1438     pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1439     pUnkOuter->refs = 1;
1440
1441     hr = CoGetPSClsid(riid, &clsid);
1442     ok_ole_success(hr, CoGetPSClsid);
1443
1444     hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1445     ok_ole_success(hr, CoGetClassObject);
1446
1447     hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1448     ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1449     ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1450
1451     /* release our reference to the outer unknown object - the PS factory
1452      * buffer will have AddRef's it in the CreateProxy call */
1453     refs = IUnknown_Release((IUnknown *)pUnkOuter);
1454     ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %ld\n", refs);
1455
1456     refs = IPSFactoryBuffer_Release(psfb);
1457 #if 0 /* not reliable on native. maybe it leaks references! */
1458     ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1459 #endif
1460
1461     refs = IUnknown_Release((IUnknown *)lpvtbl);
1462     ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1463
1464     refs = IRpcProxyBuffer_Release(proxy);
1465     ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1466 }
1467
1468 static void test_stubbuffer(REFIID riid)
1469 {
1470     HRESULT hr;
1471     IPSFactoryBuffer *psfb;
1472     IRpcStubBuffer *stub;
1473     ULONG refs;
1474     CLSID clsid;
1475
1476     cLocks = 0;
1477
1478     hr = CoGetPSClsid(riid, &clsid);
1479     ok_ole_success(hr, CoGetPSClsid);
1480
1481     hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1482     ok_ole_success(hr, CoGetClassObject);
1483
1484     hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1485     ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1486
1487     refs = IPSFactoryBuffer_Release(psfb);
1488 #if 0 /* not reliable on native. maybe it leaks references */
1489     ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1490 #endif
1491
1492     ok_more_than_one_lock();
1493
1494     IRpcStubBuffer_Disconnect(stub);
1495
1496     ok_no_locks();
1497
1498     refs = IRpcStubBuffer_Release(stub);
1499     ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1500 }
1501
1502 static HWND hwnd_app;
1503
1504 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1505     LPCLASSFACTORY iface,
1506     LPUNKNOWN pUnkOuter,
1507     REFIID riid,
1508     LPVOID *ppvObj)
1509 {
1510     DWORD_PTR res;
1511     if (IsEqualIID(riid, &IID_IWineTest))
1512     {
1513         BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1514         ok(ret, "Timed out sending a message to originating window during RPC call\n");
1515     }
1516     return S_FALSE;
1517 }
1518
1519 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1520 {
1521     Test_IClassFactory_QueryInterface,
1522     Test_IClassFactory_AddRef,
1523     Test_IClassFactory_Release,
1524     TestRE_IClassFactory_CreateInstance,
1525     Test_IClassFactory_LockServer
1526 };
1527
1528 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1529
1530 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1531 {
1532     switch (msg)
1533     {
1534     case WM_USER:
1535     {
1536         HRESULT hr;
1537         IStream *pStream = NULL;
1538         IClassFactory *proxy = NULL;
1539         IUnknown *object;
1540         DWORD tid;
1541         HANDLE thread;
1542
1543         cLocks = 0;
1544
1545         hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1546         ok_ole_success(hr, CreateStreamOnHGlobal);
1547         tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1548
1549         ok_more_than_one_lock();
1550
1551         IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1552         hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1553         ok_ole_success(hr, CoReleaseMarshalData);
1554         IStream_Release(pStream);
1555
1556         ok_more_than_one_lock();
1557
1558         /* note the use of the magic IID_IWineTest value to tell remote thread
1559          * to try to send a message back to us */
1560         hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1561
1562         IClassFactory_Release(proxy);
1563
1564         ok_no_locks();
1565
1566         end_host_object(tid, thread);
1567
1568         PostMessage(hwnd, WM_QUIT, 0, 0);
1569
1570         return 0;
1571     }
1572     case WM_USER+1:
1573     {
1574         HRESULT hr;
1575         IStream *pStream = NULL;
1576         IClassFactory *proxy = NULL;
1577         IUnknown *object;
1578         DWORD tid;
1579         HANDLE thread;
1580
1581         cLocks = 0;
1582
1583         hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1584         ok_ole_success(hr, CreateStreamOnHGlobal);
1585         tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1586
1587         ok_more_than_one_lock();
1588
1589         IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1590         hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1591         ok_ole_success(hr, CoReleaseMarshalData);
1592         IStream_Release(pStream);
1593
1594         ok_more_than_one_lock();
1595
1596         /* post quit message before a doing a COM call to show that a pending
1597         * WM_QUIT message doesn't stop the call from succeeding */
1598         PostMessage(hwnd, WM_QUIT, 0, 0);
1599         hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1600
1601         IClassFactory_Release(proxy);
1602
1603         ok_no_locks();
1604
1605         end_host_object(tid, thread);
1606
1607         return 0;
1608     }
1609     default:
1610         return DefWindowProc(hwnd, msg, wparam, lparam);
1611     }
1612 }
1613
1614 static void test_message_reentrancy(void)
1615 {
1616     WNDCLASS wndclass;
1617     MSG msg;
1618
1619     memset(&wndclass, 0, sizeof(wndclass));
1620     wndclass.lpfnWndProc = window_proc;
1621     wndclass.lpszClassName = "WineCOMTest";
1622     RegisterClass(&wndclass);
1623
1624     hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1625     ok(hwnd_app != NULL, "Window creation failed\n");
1626
1627     /* start message re-entrancy test */
1628     PostMessage(hwnd_app, WM_USER, 0, 0);
1629
1630     while (GetMessage(&msg, NULL, 0, 0))
1631     {
1632         TranslateMessage(&msg);
1633         DispatchMessage(&msg);
1634     }
1635 }
1636
1637 static void test_WM_QUIT_handling(void)
1638 {
1639     MSG msg;
1640
1641     hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1642     ok(hwnd_app != NULL, "Window creation failed\n");
1643
1644     /* start WM_QUIT handling test */
1645     PostMessage(hwnd_app, WM_USER+1, 0, 0);
1646
1647     while (GetMessage(&msg, NULL, 0, 0))
1648     {
1649         TranslateMessage(&msg);
1650         DispatchMessage(&msg);
1651     }
1652 }
1653
1654 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
1655 {
1656     HGLOBAL hglobal;
1657     DWORD size;
1658     char *marshal_data;
1659     HRESULT hr;
1660
1661     hr = GetHGlobalFromStream(pStream, &hglobal);
1662     ok_ole_success(hr, GetHGlobalFromStream);
1663
1664     size = GlobalSize(hglobal);
1665
1666     marshal_data = (char *)GlobalLock(hglobal);
1667
1668     if (mshctx == MSHCTX_INPROC)
1669     {
1670         DWORD expected_size = sizeof(DWORD) + sizeof(void *) + sizeof(DWORD) + sizeof(GUID);
1671         ok(size == expected_size, "size should have been %ld instead of %ld\n", expected_size, size);
1672
1673         ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%lx, but got 0x%lx for mshctx\n", mshlflags, *(DWORD *)marshal_data);
1674         marshal_data += sizeof(DWORD);
1675         ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
1676         marshal_data += sizeof(void *);
1677         ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%lx\n", *(DWORD *)marshal_data);
1678         marshal_data += sizeof(DWORD);
1679         trace("got guid data: {%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1680             ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
1681             ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
1682             ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
1683     }
1684     else
1685     {
1686         ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %ld\n", size);
1687         ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
1688             "marshal data should be filled by standard marshal and start with MEOW signature\n");
1689     }
1690
1691     GlobalUnlock(hglobal);
1692 }
1693
1694 static void test_freethreadedmarshaler(void)
1695 {
1696     HRESULT hr;
1697     IUnknown *pFTUnknown;
1698     IMarshal *pFTMarshal;
1699     IStream *pStream;
1700     IUnknown *pProxy;
1701     static const LARGE_INTEGER llZero;
1702
1703     cLocks = 0;
1704     hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
1705     ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
1706     hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
1707     ok_ole_success(hr, IUnknown_QueryInterface);
1708     IUnknown_Release(pFTUnknown);
1709
1710     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1711     ok_ole_success(hr, CreateStreamOnHGlobal);
1712
1713     /* inproc normal marshaling */
1714
1715     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1716         (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1717     ok_ole_success(hr, IMarshal_MarshalInterface);
1718
1719     ok_more_than_one_lock();
1720
1721     test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1722
1723     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1724     hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1725     ok_ole_success(hr, IMarshal_UnmarshalInterface);
1726
1727     IUnknown_Release(pProxy);
1728
1729     ok_no_locks();
1730
1731 /* native doesn't allow us to unmarshal or release the stream data,
1732  * presumably because it wants us to call CoMarshalInterface instead */
1733 #if 0
1734     /* local normal marshaling */
1735
1736     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1737     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
1738     ok_ole_success(hr, IMarshal_MarshalInterface);
1739
1740     ok_more_than_one_lock();
1741
1742     test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1743
1744     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1745     hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1746     ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1747
1748     ok_no_locks();
1749 #endif
1750
1751     /* inproc table-strong marshaling */
1752
1753     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1754     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1755         (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1756         MSHLFLAGS_TABLESTRONG);
1757     ok_ole_success(hr, IMarshal_MarshalInterface);
1758
1759     ok_more_than_one_lock();
1760
1761     test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
1762
1763     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1764     hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1765     ok_ole_success(hr, IMarshal_UnmarshalInterface);
1766
1767     IUnknown_Release(pProxy);
1768
1769     ok_more_than_one_lock();
1770
1771     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1772     hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1773     ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1774
1775     ok_no_locks();
1776
1777     /* inproc table-weak marshaling */
1778
1779     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1780     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1781         (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1782         MSHLFLAGS_TABLEWEAK);
1783     ok_ole_success(hr, IMarshal_MarshalInterface);
1784
1785     ok_no_locks();
1786
1787     test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
1788
1789     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1790     hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1791     ok_ole_success(hr, IMarshal_UnmarshalInterface);
1792
1793     ok_more_than_one_lock();
1794
1795     IUnknown_Release(pProxy);
1796
1797     ok_no_locks();
1798
1799     /* inproc normal marshaling (for extraordinary cases) */
1800
1801     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1802     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1803         (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1804     ok_ole_success(hr, IMarshal_MarshalInterface);
1805
1806     ok_more_than_one_lock();
1807
1808     /* this call shows that DisconnectObject does nothing */
1809     hr = IMarshal_DisconnectObject(pFTMarshal, 0);
1810     ok_ole_success(hr, IMarshal_DisconnectObject);
1811
1812     ok_more_than_one_lock();
1813
1814     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1815     hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1816     ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1817
1818     ok_no_locks();
1819
1820     /* doesn't enforce marshaling rules here and allows us to unmarshal the
1821      * interface, even though it was freed above */
1822     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1823     hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1824     ok_ole_success(hr, IMarshal_UnmarshalInterface);
1825
1826     ok_no_locks();
1827
1828     IStream_Release(pStream);
1829     IMarshal_Release(pFTMarshal);
1830 }
1831
1832 static HANDLE heventShutdown;
1833
1834 static void LockModuleOOP(void)
1835 {
1836     InterlockedIncrement(&cLocks); /* for test purposes only */
1837     CoAddRefServerProcess();
1838 }
1839
1840 static void UnlockModuleOOP(void)
1841 {
1842     InterlockedDecrement(&cLocks); /* for test purposes only */
1843     if (!CoReleaseServerProcess())
1844         SetEvent(heventShutdown);
1845 }
1846
1847 static HWND hwnd_app;
1848
1849 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
1850     LPCLASSFACTORY iface,
1851     REFIID riid,
1852     LPVOID *ppvObj)
1853 {
1854     if (ppvObj == NULL) return E_POINTER;
1855
1856     if (IsEqualGUID(riid, &IID_IUnknown) ||
1857         IsEqualGUID(riid, &IID_IClassFactory))
1858     {
1859         *ppvObj = (LPVOID)iface;
1860         IClassFactory_AddRef(iface);
1861         return S_OK;
1862     }
1863
1864     return E_NOINTERFACE;
1865 }
1866
1867 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
1868 {
1869     return 2; /* non-heap-based object */
1870 }
1871
1872 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
1873 {
1874     return 1; /* non-heap-based object */
1875 }
1876
1877 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
1878     LPCLASSFACTORY iface,
1879     LPUNKNOWN pUnkOuter,
1880     REFIID riid,
1881     LPVOID *ppvObj)
1882 {
1883     return CLASS_E_CLASSNOTAVAILABLE;
1884 }
1885
1886 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
1887     LPCLASSFACTORY iface,
1888     BOOL fLock)
1889 {
1890     if (fLock)
1891         LockModuleOOP();
1892     else
1893         UnlockModuleOOP();
1894     return S_OK;
1895 }
1896
1897 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
1898 {
1899     TestOOP_IClassFactory_QueryInterface,
1900     TestOOP_IClassFactory_AddRef,
1901     TestOOP_IClassFactory_Release,
1902     TestOOP_IClassFactory_CreateInstance,
1903     TestOOP_IClassFactory_LockServer
1904 };
1905
1906 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
1907
1908 /* tests functions commonly used by out of process COM servers */
1909 static void test_out_of_process_com(void)
1910 {
1911     static const CLSID CLSID_WineOOPTest = {
1912         0x5201163f,
1913         0x8164,
1914         0x4fd0,
1915         {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1916     }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
1917     DWORD cookie;
1918     HRESULT hr;
1919     IClassFactory * cf;
1920     DWORD ret;
1921
1922     heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
1923
1924     cLocks = 0;
1925
1926     /* Start the object suspended */
1927     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
1928         CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
1929     ok_ole_success(hr, CoRegisterClassObject);
1930
1931     /* ... and CoGetClassObject does not find it and fails when it looks for the
1932      * class in the registry */
1933     hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1934         NULL, &IID_IClassFactory, (LPVOID*)&cf);
1935     todo_wine {
1936     ok(hr == REGDB_E_CLASSNOTREG,
1937         "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08lx\n", hr);
1938     }
1939
1940     /* Resume the object suspended above ... */
1941     hr = CoResumeClassObjects();
1942     ok_ole_success(hr, CoResumeClassObjects);
1943
1944     /* ... and now it should succeed */
1945     hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1946         NULL, &IID_IClassFactory, (LPVOID*)&cf);
1947     ok_ole_success(hr, CoGetClassObject);
1948
1949     /* Now check the locking is working */
1950     /* NOTE: we are accessing the class directly, not through a proxy */
1951
1952     ok_no_locks();
1953
1954     hr = IClassFactory_LockServer(cf, TRUE);
1955     trace("IClassFactory_LockServer returned 0x%08lx\n", hr);
1956
1957     ok_more_than_one_lock();
1958     
1959     IClassFactory_LockServer(cf, FALSE);
1960
1961     ok_no_locks();
1962
1963     IClassFactory_Release(cf);
1964
1965     /* wait for shutdown signal */
1966     ret = WaitForSingleObject(heventShutdown, 5000);
1967     todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
1968
1969     /* try to connect again after SCM has suspended registered class objects */
1970     hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
1971         &IID_IClassFactory, (LPVOID*)&cf);
1972     todo_wine {
1973     ok(hr == CO_E_SERVER_STOPPING,
1974         "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08lx\n", hr);
1975     }
1976
1977     hr = CoRevokeClassObject(cookie);
1978     ok_ole_success(hr, CoRevokeClassObject);
1979
1980     CloseHandle(heventShutdown);
1981 }
1982
1983 static void test_ROT(void)
1984 {
1985     static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
1986         '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
1987         '2','0','4','6','E','5','8','6','C','9','2','5',0};
1988     HRESULT hr;
1989     IMoniker *pMoniker = NULL;
1990     IRunningObjectTable *pROT = NULL;
1991     DWORD dwCookie;
1992
1993     cLocks = 0;
1994
1995     hr = CreateFileMoniker(wszFileName, &pMoniker);
1996     ok_ole_success(hr, CreateClassMoniker);
1997     hr = GetRunningObjectTable(0, &pROT);
1998     ok_ole_success(hr, GetRunningObjectTable);
1999     hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
2000     ok_ole_success(hr, IRunningObjectTable_Register);
2001
2002     ok_more_than_one_lock();
2003
2004     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
2005     ok_ole_success(hr, IRunningObjectTable_Revoke);
2006
2007     ok_no_locks();
2008 }
2009
2010 struct git_params
2011 {
2012         DWORD cookie;
2013         IGlobalInterfaceTable *git;
2014 };
2015
2016 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2017 {
2018         HRESULT hr;
2019         struct git_params *params = (struct git_params *)pv;
2020         IClassFactory *cf;
2021
2022         hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2023         ok(hr == CO_E_NOTINITIALIZED,
2024                 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08lx\n",
2025                 hr);
2026
2027         CoInitialize(NULL);
2028         hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2029         ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2030         CoUninitialize();
2031
2032         return hr;
2033 }
2034
2035 static void test_globalinterfacetable(void)
2036 {
2037         HRESULT hr;
2038         IGlobalInterfaceTable *git;
2039         DWORD cookie;
2040         HANDLE thread;
2041         DWORD tid;
2042         struct git_params params;
2043         DWORD ret;
2044
2045         hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2046         ok_ole_success(hr, CoCreateInstance);
2047
2048         hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2049         ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2050
2051         params.cookie = cookie;
2052         params.git = git;
2053         /* note: params is on stack so we MUST wait for get_global_interface_proc
2054          * to exit before we can return */
2055         thread = CreateThread(NULL, 0, get_global_interface_proc, &params, 0, &tid);
2056
2057         ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2058         while (ret == WAIT_OBJECT_0 + 1)
2059         {
2060                 MSG msg;
2061                 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2062                         DispatchMessage(&msg);
2063                 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2064         }
2065
2066         CloseHandle(thread);
2067 }
2068
2069 static const char cf_marshaled[] =
2070 {
2071     0x9, 0x0, 0x0, 0x0,
2072     0x0, 0x0, 0x0, 0x0,
2073     0x9, 0x0, 0x0, 0x0,
2074     'M', 0x0, 'y', 0x0,
2075     'F', 0x0, 'o', 0x0,
2076     'r', 0x0, 'm', 0x0,
2077     'a', 0x0, 't', 0x0,
2078     0x0, 0x0
2079 };
2080
2081 static void test_marshal_CLIPFORMAT(void)
2082 {
2083     unsigned char *buffer;
2084     unsigned long size;
2085     unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2086     wireCLIPFORMAT wirecf;
2087     CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
2088     CLIPFORMAT cf2;
2089
2090     size = CLIPFORMAT_UserSize(&flags, 0, &cf);
2091     ok(size == sizeof(*wirecf) + sizeof(cf_marshaled), "Wrong size %ld\n", size);
2092
2093     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2094     CLIPFORMAT_UserMarshal(&flags, buffer, &cf);
2095     wirecf = (wireCLIPFORMAT)buffer;
2096     ok(wirecf->fContext == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", wirecf->fContext);
2097     ok(wirecf->u.dwValue == cf, "Marshaled value should be 0x%04x instead of 0x%04lx\n", cf, wirecf->u.dwValue);
2098     ok(!memcmp(wirecf+1, cf_marshaled, sizeof(cf_marshaled)), "Marshaled data differs\n");
2099
2100     CLIPFORMAT_UserUnmarshal(&flags, buffer, &cf2);
2101     ok(cf == cf2, "Didn't unmarshal properly\n");
2102     HeapFree(GetProcessHeap(), 0, buffer);
2103
2104     CLIPFORMAT_UserFree(&flags, &cf2);
2105 }
2106
2107 static void test_marshal_HWND(void)
2108 {
2109     unsigned char *buffer;
2110     unsigned long size;
2111     unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2112     HWND hwnd = GetDesktopWindow();
2113     HWND hwnd2;
2114     wireHWND wirehwnd;
2115
2116     size = HWND_UserSize(&flags, 0, &hwnd);
2117     ok(size == sizeof(*wirehwnd), "Wrong size %ld\n", size);
2118
2119     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2120     HWND_UserMarshal(&flags, buffer, &hwnd);
2121     wirehwnd = (wireHWND)buffer;
2122     ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext);
2123     ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote);
2124
2125     HWND_UserUnmarshal(&flags, buffer, &hwnd2);
2126     ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
2127     HeapFree(GetProcessHeap(), 0, buffer);
2128
2129     HWND_UserFree(&flags, &hwnd2);
2130 }
2131
2132 static void test_marshal_HGLOBAL(void)
2133 {
2134     unsigned char *buffer;
2135     unsigned long size;
2136     unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2137     HGLOBAL hglobal;
2138     HGLOBAL hglobal2;
2139     unsigned char *wirehglobal;
2140     int i;
2141
2142     hglobal = NULL;
2143     flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2144     size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2145     /* native is poorly programmed and allocates 4 bytes more than it needs to
2146      * here - Wine doesn't have to emulate that */
2147     ok((size == 8) || (size == 12), "Size should be 12, instead of %ld\n", size);
2148     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2149     HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2150     wirehglobal = buffer;
2151     ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
2152     wirehglobal += sizeof(ULONG);
2153     ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+4 should be HGLOBAL\n");
2154     HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2155     ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
2156     HeapFree(GetProcessHeap(), 0, buffer);
2157     HGLOBAL_UserFree(&flags, &hglobal2);
2158
2159     hglobal = GlobalAlloc(0, 4);
2160     buffer = GlobalLock(hglobal);
2161     for (i = 0; i < 4; i++)
2162         buffer[i] = i;
2163     GlobalUnlock(hglobal);
2164     flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2165     size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2166     /* native is poorly programmed and allocates 4 bytes more than it needs to
2167      * here - Wine doesn't have to emulate that */
2168     ok((size == 24) || (size == 28), "Size should be 24 or 28, instead of %ld\n", size);
2169     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2170     HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2171     wirehglobal = buffer;
2172     ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
2173     wirehglobal += sizeof(ULONG);
2174     ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0x4 should be HGLOBAL\n");
2175     wirehglobal += sizeof(ULONG);
2176     ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL\n");
2177     wirehglobal += sizeof(ULONG);
2178     ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0xc should be HGLOBAL\n");
2179     wirehglobal += sizeof(ULONG);
2180     ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL\n");
2181     wirehglobal += sizeof(ULONG);
2182     for (i = 0; i < 4; i++)
2183         ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
2184     HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2185     ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
2186     HeapFree(GetProcessHeap(), 0, buffer);
2187     HGLOBAL_UserFree(&flags, &hglobal2);
2188     GlobalFree(hglobal);
2189 }
2190
2191 static HENHMETAFILE create_emf(void)
2192 {
2193     RECT rect = {0, 0, 100, 100};
2194     HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
2195     ExtTextOut(hdc, 0, 0, ETO_OPAQUE, NULL, "Test String", strlen("Test String"), NULL);
2196     return CloseEnhMetaFile(hdc);
2197 }
2198
2199 static void test_marshal_HENHMETAFILE(void)
2200 {
2201     unsigned char *buffer;
2202     unsigned long size;
2203     unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2204     HENHMETAFILE hemf;
2205     HENHMETAFILE hemf2 = NULL;
2206     unsigned char *wirehemf;
2207
2208     hemf = create_emf();
2209
2210     size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2211     ok(size > 20, "size should be at least 20 bytes, not %ld\n", size);
2212     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2213     HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2214     wirehemf = buffer;
2215     ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
2216     wirehemf += sizeof(DWORD);
2217     ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
2218     wirehemf += sizeof(DWORD);
2219     ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf);
2220     wirehemf += sizeof(DWORD);
2221     ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf);
2222     wirehemf += sizeof(DWORD);
2223     ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %ld\n", *(DWORD *)wirehemf);
2224     wirehemf += sizeof(DWORD);
2225     /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
2226      * at this point */
2227
2228     HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2229     ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
2230     HeapFree(GetProcessHeap(), 0, buffer);
2231     HENHMETAFILE_UserFree(&flags, &hemf2);
2232     DeleteEnhMetaFile(hemf);
2233
2234     /* test NULL emf */
2235     hemf = NULL;
2236
2237     size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2238     ok(size == 8, "size should be 8 bytes, not %ld\n", size);
2239     buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
2240     HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2241     wirehemf = buffer;
2242     ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
2243     wirehemf += sizeof(DWORD);
2244     ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
2245     wirehemf += sizeof(DWORD);
2246
2247     HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2248     ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
2249     HeapFree(GetProcessHeap(), 0, buffer);
2250     HENHMETAFILE_UserFree(&flags, &hemf2);
2251 }
2252
2253 START_TEST(marshal)
2254 {
2255     WNDCLASS wndclass;
2256     HMODULE hOle32 = GetModuleHandle("ole32");
2257     if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
2258
2259     /* register a window class used in several tests */
2260     memset(&wndclass, 0, sizeof(wndclass));
2261     wndclass.lpfnWndProc = window_proc;
2262     wndclass.lpszClassName = "WineCOMTest";
2263     RegisterClass(&wndclass);
2264
2265     test_cocreateinstance_proxy();
2266
2267     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2268
2269     /* FIXME: test CoCreateInstanceEx */
2270
2271     /* lifecycle management and marshaling tests */
2272     test_no_marshaler();
2273     test_normal_marshal_and_release();
2274     test_normal_marshal_and_unmarshal();
2275     test_marshal_and_unmarshal_invalid();
2276     test_interthread_marshal_and_unmarshal();
2277     test_proxy_marshal_and_unmarshal();
2278     test_proxy_marshal_and_unmarshal2();
2279     test_marshal_stub_apartment_shutdown();
2280     test_marshal_proxy_apartment_shutdown();
2281     test_marshal_proxy_mta_apartment_shutdown();
2282     test_no_couninitialize_server();
2283     test_no_couninitialize_client();
2284     test_tableweak_marshal_and_unmarshal_twice();
2285     test_tableweak_marshal_releasedata1();
2286     test_tableweak_marshal_releasedata2();
2287     test_tablestrong_marshal_and_unmarshal_twice();
2288     test_lock_object_external();
2289     test_disconnect_stub();
2290     test_normal_marshal_and_unmarshal_twice();
2291     test_hresult_marshaling();
2292     test_proxy_used_in_wrong_thread();
2293     test_message_filter();
2294     test_bad_marshal_stream();
2295     test_proxy_interfaces();
2296     test_stubbuffer(&IID_IClassFactory);
2297     test_proxybuffer(&IID_IClassFactory);
2298     test_message_reentrancy();
2299     test_WM_QUIT_handling();
2300     test_freethreadedmarshaler();
2301
2302     /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
2303     if (0) test_out_of_process_com();
2304
2305     test_ROT();
2306     test_globalinterfacetable();
2307
2308     test_marshal_CLIPFORMAT();
2309     test_marshal_HWND();
2310     test_marshal_HGLOBAL();
2311     test_marshal_HENHMETAFILE();
2312
2313     CoUninitialize();
2314     return;
2315
2316 no_test:
2317     trace("You need DCOM95 installed to run this test\n");
2318     return;
2319 }