opengl32: Avoid generating a wrapper for internal functions when we can call the...
[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 %d\n", cLocks)
39 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
40 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\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 %d\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%08x\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%08x\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     IStream_Release(ncu_params->stream);
760
761     ok_more_than_one_lock();
762
763     /* die without calling CoUninitialize */
764
765     return 0;
766 }
767
768 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
769 static void test_no_couninitialize_client(void)
770 {
771     HRESULT hr;
772     IStream *pStream = NULL;
773     DWORD tid;
774     DWORD host_tid;
775     HANDLE thread;
776     HANDLE host_thread;
777     struct ncu_params ncu_params;
778
779     cLocks = 0;
780
781     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
782     ok_ole_success(hr, CreateStreamOnHGlobal);
783     ncu_params.stream = pStream;
784
785     /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
786      * always deadlock when called from within DllMain */
787     host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
788     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
789
790     ok_more_than_one_lock();
791
792     thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
793
794     WaitForSingleObject(thread, INFINITE);
795     CloseHandle(thread);
796
797     ok_no_locks();
798
799     end_host_object(host_tid, host_thread);
800 }
801
802 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
803 static void test_tableweak_marshal_and_unmarshal_twice(void)
804 {
805     HRESULT hr;
806     IStream *pStream = NULL;
807     IUnknown *pProxy1 = NULL;
808     IUnknown *pProxy2 = NULL;
809     DWORD tid;
810     HANDLE thread;
811
812     cLocks = 0;
813
814     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
815     ok_ole_success(hr, CreateStreamOnHGlobal);
816     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
817
818     ok_more_than_one_lock();
819
820     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
821     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
822     ok_ole_success(hr, CoUnmarshalInterface);
823
824     ok_more_than_one_lock();
825
826     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
827     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
828     IStream_Release(pStream);
829     ok_ole_success(hr, CoUnmarshalInterface);
830
831     ok_more_than_one_lock();
832
833     IUnknown_Release(pProxy1);
834     IUnknown_Release(pProxy2);
835
836     /* this line is shows the difference between weak and strong table marshaling:
837      *  weak has cLocks == 0
838      *  strong has cLocks > 0 */
839     ok_no_locks();
840
841     end_host_object(tid, thread);
842 }
843
844 /* tests releasing after unmarshaling one object */
845 static void test_tableweak_marshal_releasedata1(void)
846 {
847     HRESULT hr;
848     IStream *pStream = NULL;
849     IUnknown *pProxy1 = NULL;
850     IUnknown *pProxy2 = NULL;
851     DWORD tid;
852     HANDLE thread;
853
854     cLocks = 0;
855
856     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
857     ok_ole_success(hr, CreateStreamOnHGlobal);
858     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
859
860     ok_more_than_one_lock();
861
862     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
863     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
864     ok_ole_success(hr, CoUnmarshalInterface);
865
866     ok_more_than_one_lock();
867
868     /* release the remaining reference on the object by calling
869      * CoReleaseMarshalData in the hosting thread */
870     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
871     release_host_object(tid);
872
873     ok_more_than_one_lock();
874
875     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
876     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
877     ok_ole_success(hr, CoUnmarshalInterface);
878     IStream_Release(pStream);
879
880     ok_more_than_one_lock();
881
882     IUnknown_Release(pProxy1);
883     if (pProxy2)
884         IUnknown_Release(pProxy2);
885
886     /* this line is shows the difference between weak and strong table marshaling:
887      *  weak has cLocks == 0
888      *  strong has cLocks > 0 */
889     ok_no_locks();
890
891     end_host_object(tid, thread);
892 }
893
894 /* tests releasing after unmarshaling one object */
895 static void test_tableweak_marshal_releasedata2(void)
896 {
897     HRESULT hr;
898     IStream *pStream = NULL;
899     IUnknown *pProxy = NULL;
900     DWORD tid;
901     HANDLE thread;
902
903     cLocks = 0;
904
905     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
906     ok_ole_success(hr, CreateStreamOnHGlobal);
907     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
908
909     ok_more_than_one_lock();
910
911     /* release the remaining reference on the object by calling
912      * CoReleaseMarshalData in the hosting thread */
913     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
914     release_host_object(tid);
915
916     ok_no_locks();
917
918     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
919     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
920     todo_wine
921     {
922     ok(hr == CO_E_OBJNOTREG,
923        "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
924        hr);
925     }
926     IStream_Release(pStream);
927
928     ok_no_locks();
929
930     end_host_object(tid, thread);
931 }
932
933 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
934 static void test_tablestrong_marshal_and_unmarshal_twice(void)
935 {
936     HRESULT hr;
937     IStream *pStream = NULL;
938     IUnknown *pProxy1 = NULL;
939     IUnknown *pProxy2 = NULL;
940     DWORD tid;
941     HANDLE thread;
942
943     cLocks = 0;
944
945     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
946     ok_ole_success(hr, CreateStreamOnHGlobal);
947     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
948
949     ok_more_than_one_lock();
950
951     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
952     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
953     ok_ole_success(hr, CoUnmarshalInterface);
954
955     ok_more_than_one_lock();
956
957     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
958     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
959     ok_ole_success(hr, CoUnmarshalInterface);
960
961     ok_more_than_one_lock();
962
963     if (pProxy1) IUnknown_Release(pProxy1);
964     if (pProxy2) IUnknown_Release(pProxy2);
965
966     /* this line is shows the difference between weak and strong table marshaling:
967      *  weak has cLocks == 0
968      *  strong has cLocks > 0 */
969     ok_more_than_one_lock();
970
971     /* release the remaining reference on the object by calling
972      * CoReleaseMarshalData in the hosting thread */
973     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
974     release_host_object(tid);
975     IStream_Release(pStream);
976
977     ok_no_locks();
978
979     end_host_object(tid, thread);
980 }
981
982 /* tests CoLockObjectExternal */
983 static void test_lock_object_external(void)
984 {
985     HRESULT hr;
986     IStream *pStream = NULL;
987
988     cLocks = 0;
989
990     /* test the stub manager creation aspect of CoLockObjectExternal when the
991      * object hasn't been marshaled yet */
992     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
993
994     ok_more_than_one_lock();
995
996     CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
997
998     ok_no_locks();
999
1000     /* test our empty stub manager being handled correctly in
1001      * CoMarshalInterface */
1002     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1003
1004     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1005     ok_ole_success(hr, CreateStreamOnHGlobal);
1006     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1007     ok_ole_success(hr, CoMarshalInterface);
1008
1009     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1010
1011     ok_more_than_one_lock();
1012
1013     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1014     hr = CoReleaseMarshalData(pStream);
1015     ok_ole_success(hr, CoReleaseMarshalData);
1016     IStream_Release(pStream);
1017
1018     ok_more_than_one_lock();
1019
1020     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1021
1022     ok_more_than_one_lock();
1023
1024     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1025
1026     ok_no_locks();
1027 }
1028
1029 /* tests disconnecting stubs */
1030 static void test_disconnect_stub(void)
1031 {
1032     HRESULT hr;
1033     IStream *pStream = NULL;
1034
1035     cLocks = 0;
1036
1037     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1038     ok_ole_success(hr, CreateStreamOnHGlobal);
1039     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1040     ok_ole_success(hr, CoMarshalInterface);
1041
1042     CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1043
1044     ok_more_than_one_lock();
1045     
1046     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1047     hr = CoReleaseMarshalData(pStream);
1048     ok_ole_success(hr, CoReleaseMarshalData);
1049     IStream_Release(pStream);
1050
1051     ok_more_than_one_lock();
1052
1053     CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1054
1055     ok_no_locks();
1056 }
1057
1058 /* tests failure case of a same-thread marshal and unmarshal twice */
1059 static void test_normal_marshal_and_unmarshal_twice(void)
1060 {
1061     HRESULT hr;
1062     IStream *pStream = NULL;
1063     IUnknown *pProxy1 = NULL;
1064     IUnknown *pProxy2 = NULL;
1065
1066     cLocks = 0;
1067
1068     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1069     ok_ole_success(hr, CreateStreamOnHGlobal);
1070     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1071     ok_ole_success(hr, CoMarshalInterface);
1072
1073     ok_more_than_one_lock();
1074     
1075     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1076     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1077     ok_ole_success(hr, CoUnmarshalInterface);
1078
1079     ok_more_than_one_lock();
1080
1081     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1082     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1083     ok(hr == CO_E_OBJNOTCONNECTED,
1084         "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
1085
1086     IStream_Release(pStream);
1087
1088     ok_more_than_one_lock();
1089
1090     IUnknown_Release(pProxy1);
1091
1092     ok_no_locks();
1093 }
1094
1095 /* tests success case of marshaling and unmarshaling an HRESULT */
1096 static void test_hresult_marshaling(void)
1097 {
1098     HRESULT hr;
1099     HRESULT hr_marshaled = 0;
1100     IStream *pStream = NULL;
1101     static const HRESULT E_DEADBEEF = 0xdeadbeef;
1102
1103     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1104     ok_ole_success(hr, CreateStreamOnHGlobal);
1105
1106     hr = CoMarshalHresult(pStream, E_DEADBEEF);
1107     ok_ole_success(hr, CoMarshalHresult);
1108
1109     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1110     hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1111     ok_ole_success(hr, IStream_Read);
1112
1113     ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1114
1115     hr_marshaled = 0;
1116     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1117     hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1118     ok_ole_success(hr, CoUnmarshalHresult);
1119
1120     ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1121
1122     IStream_Release(pStream);
1123 }
1124
1125
1126 /* helper for test_proxy_used_in_wrong_thread */
1127 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1128 {
1129     IClassFactory * cf = (IClassFactory *)p;
1130     HRESULT hr;
1131     IUnknown * proxy = NULL;
1132
1133     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1134
1135     hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1136     if (proxy) IUnknown_Release(proxy);
1137     ok(hr == RPC_E_WRONG_THREAD,
1138         "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1139         hr);
1140
1141     CoUninitialize();
1142
1143     return 0;
1144 }
1145
1146 /* tests failure case of a using a proxy in the wrong apartment */
1147 static void test_proxy_used_in_wrong_thread(void)
1148 {
1149     HRESULT hr;
1150     IStream *pStream = NULL;
1151     IUnknown *pProxy = NULL;
1152     DWORD tid, tid2;
1153     HANDLE thread;
1154     HANDLE host_thread;
1155
1156     cLocks = 0;
1157
1158     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1159     ok_ole_success(hr, CreateStreamOnHGlobal);
1160     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1161
1162     ok_more_than_one_lock();
1163     
1164     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1165     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1166     ok_ole_success(hr, CoUnmarshalInterface);
1167     IStream_Release(pStream);
1168
1169     ok_more_than_one_lock();
1170
1171     /* create a thread that we can misbehave in */
1172     thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1173
1174     WaitForSingleObject(thread, INFINITE);
1175     CloseHandle(thread);
1176
1177     IUnknown_Release(pProxy);
1178
1179     ok_no_locks();
1180
1181     end_host_object(tid, host_thread);
1182 }
1183
1184 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1185 {
1186     if (ppvObj == NULL) return E_POINTER;
1187
1188     if (IsEqualGUID(riid, &IID_IUnknown) ||
1189         IsEqualGUID(riid, &IID_IClassFactory))
1190     {
1191         *ppvObj = (LPVOID)iface;
1192         IClassFactory_AddRef(iface);
1193         return S_OK;
1194     }
1195
1196     return E_NOINTERFACE;
1197 }
1198
1199 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1200 {
1201     return 2; /* non-heap object */
1202 }
1203
1204 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1205 {
1206     return 1; /* non-heap object */
1207 }
1208
1209 static DWORD WINAPI MessageFilter_HandleInComingCall(
1210   IMessageFilter *iface,
1211   DWORD dwCallType,
1212   HTASK threadIDCaller,
1213   DWORD dwTickCount,
1214   LPINTERFACEINFO lpInterfaceInfo)
1215 {
1216     static int callcount = 0;
1217     DWORD ret;
1218     trace("HandleInComingCall\n");
1219     switch (callcount)
1220     {
1221     case 0:
1222         ret = SERVERCALL_REJECTED;
1223         break;
1224     case 1:
1225         ret = SERVERCALL_RETRYLATER;
1226         break;
1227     default:
1228         ret = SERVERCALL_ISHANDLED;
1229         break;
1230     }
1231     callcount++;
1232     return ret;
1233 }
1234
1235 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1236   IMessageFilter *iface,
1237   HTASK threadIDCallee,
1238   DWORD dwTickCount,
1239   DWORD dwRejectType)
1240 {
1241     trace("RetryRejectedCall\n");
1242     return 0;
1243 }
1244
1245 static DWORD WINAPI MessageFilter_MessagePending(
1246   IMessageFilter *iface,
1247   HTASK threadIDCallee,
1248   DWORD dwTickCount,
1249   DWORD dwPendingType)
1250 {
1251     trace("MessagePending\n");
1252     return PENDINGMSG_WAITNOPROCESS;
1253 }
1254
1255 static const IMessageFilterVtbl MessageFilter_Vtbl =
1256 {
1257     MessageFilter_QueryInterface,
1258     MessageFilter_AddRef,
1259     MessageFilter_Release,
1260     MessageFilter_HandleInComingCall,
1261     MessageFilter_RetryRejectedCall,
1262     MessageFilter_MessagePending
1263 };
1264
1265 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1266
1267 static void test_message_filter(void)
1268 {
1269     HRESULT hr;
1270     IStream *pStream = NULL;
1271     IClassFactory *cf = NULL;
1272     DWORD tid;
1273     IUnknown *proxy = NULL;
1274     IMessageFilter *prev_filter = NULL;
1275     HANDLE thread;
1276
1277     cLocks = 0;
1278
1279     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1280     ok_ole_success(hr, CreateStreamOnHGlobal);
1281     tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1282
1283     ok_more_than_one_lock();
1284
1285     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1286     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1287     ok_ole_success(hr, CoUnmarshalInterface);
1288     IStream_Release(pStream);
1289
1290     ok_more_than_one_lock();
1291
1292     hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1293     todo_wine { ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr); }
1294     if (proxy) IUnknown_Release(proxy);
1295     proxy = NULL;
1296
1297     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1298     ok_ole_success(hr, CoRegisterMessageFilter);
1299     if (prev_filter) IMessageFilter_Release(prev_filter);
1300
1301     hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1302     ok_ole_success(hr, IClassFactory_CreateInstance);
1303
1304     IUnknown_Release(proxy);
1305
1306     IClassFactory_Release(cf);
1307
1308     ok_no_locks();
1309
1310     end_host_object(tid, thread);
1311 }
1312
1313 /* test failure case of trying to unmarshal from bad stream */
1314 static void test_bad_marshal_stream(void)
1315 {
1316     HRESULT hr;
1317     IStream *pStream = NULL;
1318
1319     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1320     ok_ole_success(hr, CreateStreamOnHGlobal);
1321     hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1322     ok_ole_success(hr, CoMarshalInterface);
1323
1324     ok_more_than_one_lock();
1325
1326     /* try to read beyond end of stream */
1327     hr = CoReleaseMarshalData(pStream);
1328     ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
1329
1330     /* now release for real */
1331     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1332     hr = CoReleaseMarshalData(pStream);
1333     ok_ole_success(hr, CoReleaseMarshalData);
1334
1335     IStream_Release(pStream);
1336 }
1337
1338 /* tests that proxies implement certain interfaces */
1339 static void test_proxy_interfaces(void)
1340 {
1341     HRESULT hr;
1342     IStream *pStream = NULL;
1343     IUnknown *pProxy = NULL;
1344     IUnknown *pOtherUnknown = NULL;
1345     DWORD tid;
1346     HANDLE thread;
1347
1348     cLocks = 0;
1349
1350     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1351     ok_ole_success(hr, CreateStreamOnHGlobal);
1352     tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1353
1354     ok_more_than_one_lock();
1355         
1356     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1357     hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1358     ok_ole_success(hr, CoUnmarshalInterface);
1359     IStream_Release(pStream);
1360
1361     ok_more_than_one_lock();
1362
1363     hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1364     ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1365     if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1366
1367     hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1368     todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); }
1369     if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1370
1371     hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1372     ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1373     if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1374
1375     hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1376     ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1377     if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1378
1379     /* IMarshal2 is also supported on NT-based systems, but is pretty much
1380      * useless as it has no more methods over IMarshal that it inherits from. */
1381
1382     IUnknown_Release(pProxy);
1383
1384     ok_no_locks();
1385
1386     end_host_object(tid, thread);
1387 }
1388
1389 typedef struct
1390 {
1391     const IUnknownVtbl *lpVtbl;
1392     ULONG refs;
1393 } HeapUnknown;
1394
1395 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1396 {
1397     if (IsEqualIID(riid, &IID_IUnknown))
1398     {
1399         IUnknown_AddRef(iface);
1400         *ppv = (LPVOID)iface;
1401         return S_OK;
1402     }
1403     *ppv = NULL;
1404     return E_NOINTERFACE;
1405 }
1406
1407 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1408 {
1409     HeapUnknown *This = (HeapUnknown *)iface;
1410     trace("HeapUnknown_AddRef(%p)\n", iface);
1411     return InterlockedIncrement((LONG*)&This->refs);
1412 }
1413
1414 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1415 {
1416     HeapUnknown *This = (HeapUnknown *)iface;
1417     ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1418     trace("HeapUnknown_Release(%p)\n", iface);
1419     if (!refs) HeapFree(GetProcessHeap(), 0, This);
1420     return refs;
1421 }
1422
1423 static const IUnknownVtbl HeapUnknown_Vtbl =
1424 {
1425     HeapUnknown_QueryInterface,
1426     HeapUnknown_AddRef,
1427     HeapUnknown_Release
1428 };
1429
1430 static void test_proxybuffer(REFIID riid)
1431 {
1432     HRESULT hr;
1433     IPSFactoryBuffer *psfb;
1434     IRpcProxyBuffer *proxy;
1435     LPVOID lpvtbl;
1436     ULONG refs;
1437     CLSID clsid;
1438     HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1439
1440     pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1441     pUnkOuter->refs = 1;
1442
1443     hr = CoGetPSClsid(riid, &clsid);
1444     ok_ole_success(hr, CoGetPSClsid);
1445
1446     hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1447     ok_ole_success(hr, CoGetClassObject);
1448
1449     hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1450     ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1451     ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1452
1453     /* release our reference to the outer unknown object - the PS factory
1454      * buffer will have AddRef's it in the CreateProxy call */
1455     refs = IUnknown_Release((IUnknown *)pUnkOuter);
1456     ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
1457
1458     refs = IPSFactoryBuffer_Release(psfb);
1459 #if 0 /* not reliable on native. maybe it leaks references! */
1460     ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1461 #endif
1462
1463     refs = IUnknown_Release((IUnknown *)lpvtbl);
1464     ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1465
1466     refs = IRpcProxyBuffer_Release(proxy);
1467     ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1468 }
1469
1470 static void test_stubbuffer(REFIID riid)
1471 {
1472     HRESULT hr;
1473     IPSFactoryBuffer *psfb;
1474     IRpcStubBuffer *stub;
1475     ULONG refs;
1476     CLSID clsid;
1477
1478     cLocks = 0;
1479
1480     hr = CoGetPSClsid(riid, &clsid);
1481     ok_ole_success(hr, CoGetPSClsid);
1482
1483     hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1484     ok_ole_success(hr, CoGetClassObject);
1485
1486     hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1487     ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1488
1489     refs = IPSFactoryBuffer_Release(psfb);
1490 #if 0 /* not reliable on native. maybe it leaks references */
1491     ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1492 #endif
1493
1494     ok_more_than_one_lock();
1495
1496     IRpcStubBuffer_Disconnect(stub);
1497
1498     ok_no_locks();
1499
1500     refs = IRpcStubBuffer_Release(stub);
1501     ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1502 }
1503
1504 static HWND hwnd_app;
1505
1506 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1507     LPCLASSFACTORY iface,
1508     LPUNKNOWN pUnkOuter,
1509     REFIID riid,
1510     LPVOID *ppvObj)
1511 {
1512     DWORD_PTR res;
1513     if (IsEqualIID(riid, &IID_IWineTest))
1514     {
1515         BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1516         ok(ret, "Timed out sending a message to originating window during RPC call\n");
1517     }
1518     return S_FALSE;
1519 }
1520
1521 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1522 {
1523     Test_IClassFactory_QueryInterface,
1524     Test_IClassFactory_AddRef,
1525     Test_IClassFactory_Release,
1526     TestRE_IClassFactory_CreateInstance,
1527     Test_IClassFactory_LockServer
1528 };
1529
1530 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1531
1532 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1533 {
1534     switch (msg)
1535     {
1536     case WM_USER:
1537     {
1538         HRESULT hr;
1539         IStream *pStream = NULL;
1540         IClassFactory *proxy = NULL;
1541         IUnknown *object;
1542         DWORD tid;
1543         HANDLE thread;
1544
1545         cLocks = 0;
1546
1547         hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1548         ok_ole_success(hr, CreateStreamOnHGlobal);
1549         tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1550
1551         ok_more_than_one_lock();
1552
1553         IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1554         hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1555         ok_ole_success(hr, CoReleaseMarshalData);
1556         IStream_Release(pStream);
1557
1558         ok_more_than_one_lock();
1559
1560         /* note the use of the magic IID_IWineTest value to tell remote thread
1561          * to try to send a message back to us */
1562         hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1563
1564         IClassFactory_Release(proxy);
1565
1566         ok_no_locks();
1567
1568         end_host_object(tid, thread);
1569
1570         PostMessage(hwnd, WM_QUIT, 0, 0);
1571
1572         return 0;
1573     }
1574     case WM_USER+1:
1575     {
1576         HRESULT hr;
1577         IStream *pStream = NULL;
1578         IClassFactory *proxy = NULL;
1579         IUnknown *object;
1580         DWORD tid;
1581         HANDLE thread;
1582
1583         cLocks = 0;
1584
1585         hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1586         ok_ole_success(hr, CreateStreamOnHGlobal);
1587         tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1588
1589         ok_more_than_one_lock();
1590
1591         IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1592         hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1593         ok_ole_success(hr, CoReleaseMarshalData);
1594         IStream_Release(pStream);
1595
1596         ok_more_than_one_lock();
1597
1598         /* post quit message before a doing a COM call to show that a pending
1599         * WM_QUIT message doesn't stop the call from succeeding */
1600         PostMessage(hwnd, WM_QUIT, 0, 0);
1601         hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1602
1603         IClassFactory_Release(proxy);
1604
1605         ok_no_locks();
1606
1607         end_host_object(tid, thread);
1608
1609         return 0;
1610     }
1611     default:
1612         return DefWindowProc(hwnd, msg, wparam, lparam);
1613     }
1614 }
1615
1616 static void test_message_reentrancy(void)
1617 {
1618     WNDCLASS wndclass;
1619     MSG msg;
1620
1621     memset(&wndclass, 0, sizeof(wndclass));
1622     wndclass.lpfnWndProc = window_proc;
1623     wndclass.lpszClassName = "WineCOMTest";
1624     RegisterClass(&wndclass);
1625
1626     hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1627     ok(hwnd_app != NULL, "Window creation failed\n");
1628
1629     /* start message re-entrancy test */
1630     PostMessage(hwnd_app, WM_USER, 0, 0);
1631
1632     while (GetMessage(&msg, NULL, 0, 0))
1633     {
1634         TranslateMessage(&msg);
1635         DispatchMessage(&msg);
1636     }
1637 }
1638
1639 static void test_WM_QUIT_handling(void)
1640 {
1641     MSG msg;
1642
1643     hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1644     ok(hwnd_app != NULL, "Window creation failed\n");
1645
1646     /* start WM_QUIT handling test */
1647     PostMessage(hwnd_app, WM_USER+1, 0, 0);
1648
1649     while (GetMessage(&msg, NULL, 0, 0))
1650     {
1651         TranslateMessage(&msg);
1652         DispatchMessage(&msg);
1653     }
1654 }
1655
1656 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
1657 {
1658     HGLOBAL hglobal;
1659     DWORD size;
1660     char *marshal_data;
1661     HRESULT hr;
1662
1663     hr = GetHGlobalFromStream(pStream, &hglobal);
1664     ok_ole_success(hr, GetHGlobalFromStream);
1665
1666     size = GlobalSize(hglobal);
1667
1668     marshal_data = (char *)GlobalLock(hglobal);
1669
1670     if (mshctx == MSHCTX_INPROC)
1671     {
1672         DWORD expected_size = sizeof(DWORD) + sizeof(void *) + sizeof(DWORD) + sizeof(GUID);
1673         ok(size == expected_size, "size should have been %d instead of %d\n", expected_size, size);
1674
1675         ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
1676         marshal_data += sizeof(DWORD);
1677         ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
1678         marshal_data += sizeof(void *);
1679         ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
1680         marshal_data += sizeof(DWORD);
1681         trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1682             ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
1683             ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
1684             ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
1685     }
1686     else
1687     {
1688         ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
1689         ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
1690             "marshal data should be filled by standard marshal and start with MEOW signature\n");
1691     }
1692
1693     GlobalUnlock(hglobal);
1694 }
1695
1696 static void test_freethreadedmarshaler(void)
1697 {
1698     HRESULT hr;
1699     IUnknown *pFTUnknown;
1700     IMarshal *pFTMarshal;
1701     IStream *pStream;
1702     IUnknown *pProxy;
1703     static const LARGE_INTEGER llZero;
1704
1705     cLocks = 0;
1706     hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
1707     ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
1708     hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
1709     ok_ole_success(hr, IUnknown_QueryInterface);
1710     IUnknown_Release(pFTUnknown);
1711
1712     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1713     ok_ole_success(hr, CreateStreamOnHGlobal);
1714
1715     /* inproc normal marshaling */
1716
1717     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1718         (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1719     ok_ole_success(hr, IMarshal_MarshalInterface);
1720
1721     ok_more_than_one_lock();
1722
1723     test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1724
1725     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1726     hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1727     ok_ole_success(hr, IMarshal_UnmarshalInterface);
1728
1729     IUnknown_Release(pProxy);
1730
1731     ok_no_locks();
1732
1733 /* native doesn't allow us to unmarshal or release the stream data,
1734  * presumably because it wants us to call CoMarshalInterface instead */
1735 #if 0
1736     /* local normal marshaling */
1737
1738     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1739     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
1740     ok_ole_success(hr, IMarshal_MarshalInterface);
1741
1742     ok_more_than_one_lock();
1743
1744     test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1745
1746     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1747     hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1748     ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1749
1750     ok_no_locks();
1751 #endif
1752
1753     /* inproc table-strong marshaling */
1754
1755     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1756     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1757         (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1758         MSHLFLAGS_TABLESTRONG);
1759     ok_ole_success(hr, IMarshal_MarshalInterface);
1760
1761     ok_more_than_one_lock();
1762
1763     test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
1764
1765     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1766     hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1767     ok_ole_success(hr, IMarshal_UnmarshalInterface);
1768
1769     IUnknown_Release(pProxy);
1770
1771     ok_more_than_one_lock();
1772
1773     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1774     hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1775     ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1776
1777     ok_no_locks();
1778
1779     /* inproc table-weak marshaling */
1780
1781     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1782     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1783         (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1784         MSHLFLAGS_TABLEWEAK);
1785     ok_ole_success(hr, IMarshal_MarshalInterface);
1786
1787     ok_no_locks();
1788
1789     test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
1790
1791     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1792     hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1793     ok_ole_success(hr, IMarshal_UnmarshalInterface);
1794
1795     ok_more_than_one_lock();
1796
1797     IUnknown_Release(pProxy);
1798
1799     ok_no_locks();
1800
1801     /* inproc normal marshaling (for extraordinary cases) */
1802
1803     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1804     hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1805         (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1806     ok_ole_success(hr, IMarshal_MarshalInterface);
1807
1808     ok_more_than_one_lock();
1809
1810     /* this call shows that DisconnectObject does nothing */
1811     hr = IMarshal_DisconnectObject(pFTMarshal, 0);
1812     ok_ole_success(hr, IMarshal_DisconnectObject);
1813
1814     ok_more_than_one_lock();
1815
1816     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1817     hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1818     ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1819
1820     ok_no_locks();
1821
1822     /* doesn't enforce marshaling rules here and allows us to unmarshal the
1823      * interface, even though it was freed above */
1824     IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1825     hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1826     ok_ole_success(hr, IMarshal_UnmarshalInterface);
1827
1828     ok_no_locks();
1829
1830     IStream_Release(pStream);
1831     IMarshal_Release(pFTMarshal);
1832 }
1833
1834 static HANDLE heventShutdown;
1835
1836 static void LockModuleOOP(void)
1837 {
1838     InterlockedIncrement(&cLocks); /* for test purposes only */
1839     CoAddRefServerProcess();
1840 }
1841
1842 static void UnlockModuleOOP(void)
1843 {
1844     InterlockedDecrement(&cLocks); /* for test purposes only */
1845     if (!CoReleaseServerProcess())
1846         SetEvent(heventShutdown);
1847 }
1848
1849 static HWND hwnd_app;
1850
1851 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
1852     LPCLASSFACTORY iface,
1853     REFIID riid,
1854     LPVOID *ppvObj)
1855 {
1856     if (ppvObj == NULL) return E_POINTER;
1857
1858     if (IsEqualGUID(riid, &IID_IUnknown) ||
1859         IsEqualGUID(riid, &IID_IClassFactory))
1860     {
1861         *ppvObj = (LPVOID)iface;
1862         IClassFactory_AddRef(iface);
1863         return S_OK;
1864     }
1865
1866     return E_NOINTERFACE;
1867 }
1868
1869 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
1870 {
1871     return 2; /* non-heap-based object */
1872 }
1873
1874 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
1875 {
1876     return 1; /* non-heap-based object */
1877 }
1878
1879 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
1880     LPCLASSFACTORY iface,
1881     LPUNKNOWN pUnkOuter,
1882     REFIID riid,
1883     LPVOID *ppvObj)
1884 {
1885     return CLASS_E_CLASSNOTAVAILABLE;
1886 }
1887
1888 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
1889     LPCLASSFACTORY iface,
1890     BOOL fLock)
1891 {
1892     if (fLock)
1893         LockModuleOOP();
1894     else
1895         UnlockModuleOOP();
1896     return S_OK;
1897 }
1898
1899 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
1900 {
1901     TestOOP_IClassFactory_QueryInterface,
1902     TestOOP_IClassFactory_AddRef,
1903     TestOOP_IClassFactory_Release,
1904     TestOOP_IClassFactory_CreateInstance,
1905     TestOOP_IClassFactory_LockServer
1906 };
1907
1908 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
1909
1910 /* tests functions commonly used by out of process COM servers */
1911 static void test_out_of_process_com(void)
1912 {
1913     static const CLSID CLSID_WineOOPTest = {
1914         0x5201163f,
1915         0x8164,
1916         0x4fd0,
1917         {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1918     }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
1919     DWORD cookie;
1920     HRESULT hr;
1921     IClassFactory * cf;
1922     DWORD ret;
1923
1924     heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
1925
1926     cLocks = 0;
1927
1928     /* Start the object suspended */
1929     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
1930         CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
1931     ok_ole_success(hr, CoRegisterClassObject);
1932
1933     /* ... and CoGetClassObject does not find it and fails when it looks for the
1934      * class in the registry */
1935     hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1936         NULL, &IID_IClassFactory, (LPVOID*)&cf);
1937     todo_wine {
1938     ok(hr == REGDB_E_CLASSNOTREG,
1939         "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
1940     }
1941
1942     /* Resume the object suspended above ... */
1943     hr = CoResumeClassObjects();
1944     ok_ole_success(hr, CoResumeClassObjects);
1945
1946     /* ... and now it should succeed */
1947     hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1948         NULL, &IID_IClassFactory, (LPVOID*)&cf);
1949     ok_ole_success(hr, CoGetClassObject);
1950
1951     /* Now check the locking is working */
1952     /* NOTE: we are accessing the class directly, not through a proxy */
1953
1954     ok_no_locks();
1955
1956     hr = IClassFactory_LockServer(cf, TRUE);
1957     trace("IClassFactory_LockServer returned 0x%08x\n", hr);
1958
1959     ok_more_than_one_lock();
1960     
1961     IClassFactory_LockServer(cf, FALSE);
1962
1963     ok_no_locks();
1964
1965     IClassFactory_Release(cf);
1966
1967     /* wait for shutdown signal */
1968     ret = WaitForSingleObject(heventShutdown, 5000);
1969     todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
1970
1971     /* try to connect again after SCM has suspended registered class objects */
1972     hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
1973         &IID_IClassFactory, (LPVOID*)&cf);
1974     todo_wine {
1975     ok(hr == CO_E_SERVER_STOPPING,
1976         "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr);
1977     }
1978
1979     hr = CoRevokeClassObject(cookie);
1980     ok_ole_success(hr, CoRevokeClassObject);
1981
1982     CloseHandle(heventShutdown);
1983 }
1984
1985 static void test_ROT(void)
1986 {
1987     static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
1988         '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
1989         '2','0','4','6','E','5','8','6','C','9','2','5',0};
1990     HRESULT hr;
1991     IMoniker *pMoniker = NULL;
1992     IRunningObjectTable *pROT = NULL;
1993     DWORD dwCookie;
1994
1995     cLocks = 0;
1996
1997     hr = CreateFileMoniker(wszFileName, &pMoniker);
1998     ok_ole_success(hr, CreateClassMoniker);
1999     hr = GetRunningObjectTable(0, &pROT);
2000     ok_ole_success(hr, GetRunningObjectTable);
2001     hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
2002     ok_ole_success(hr, IRunningObjectTable_Register);
2003     IMoniker_Release(pMoniker);
2004
2005     ok_more_than_one_lock();
2006
2007     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
2008     ok_ole_success(hr, IRunningObjectTable_Revoke);
2009
2010     ok_no_locks();
2011 }
2012
2013 struct git_params
2014 {
2015         DWORD cookie;
2016         IGlobalInterfaceTable *git;
2017 };
2018
2019 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2020 {
2021         HRESULT hr;
2022         struct git_params *params = (struct git_params *)pv;
2023         IClassFactory *cf;
2024
2025         hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2026         ok(hr == CO_E_NOTINITIALIZED,
2027                 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
2028                 hr);
2029
2030         CoInitialize(NULL);
2031         hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2032         ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2033         CoUninitialize();
2034
2035         return hr;
2036 }
2037
2038 static void test_globalinterfacetable(void)
2039 {
2040         HRESULT hr;
2041         IGlobalInterfaceTable *git;
2042         DWORD cookie;
2043         HANDLE thread;
2044         DWORD tid;
2045         struct git_params params;
2046         DWORD ret;
2047
2048         hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2049         ok_ole_success(hr, CoCreateInstance);
2050
2051         hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2052         ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2053
2054         params.cookie = cookie;
2055         params.git = git;
2056         /* note: params is on stack so we MUST wait for get_global_interface_proc
2057          * to exit before we can return */
2058         thread = CreateThread(NULL, 0, get_global_interface_proc, &params, 0, &tid);
2059
2060         ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2061         while (ret == WAIT_OBJECT_0 + 1)
2062         {
2063                 MSG msg;
2064                 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2065                         DispatchMessage(&msg);
2066                 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2067         }
2068
2069         CloseHandle(thread);
2070 }
2071
2072 static const char cf_marshaled[] =
2073 {
2074     0x9, 0x0, 0x0, 0x0,
2075     0x0, 0x0, 0x0, 0x0,
2076     0x9, 0x0, 0x0, 0x0,
2077     'M', 0x0, 'y', 0x0,
2078     'F', 0x0, 'o', 0x0,
2079     'r', 0x0, 'm', 0x0,
2080     'a', 0x0, 't', 0x0,
2081     0x0, 0x0
2082 };
2083
2084 static void test_marshal_CLIPFORMAT(void)
2085 {
2086     unsigned char *buffer;
2087     ULONG size;
2088     ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2089     wireCLIPFORMAT wirecf;
2090     CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
2091     CLIPFORMAT cf2;
2092
2093     size = CLIPFORMAT_UserSize(&flags, 0, &cf);
2094     ok(size == sizeof(*wirecf) + sizeof(cf_marshaled), "Wrong size %d\n", size);
2095
2096     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2097     CLIPFORMAT_UserMarshal(&flags, buffer, &cf);
2098     wirecf = (wireCLIPFORMAT)buffer;
2099     ok(wirecf->fContext == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", wirecf->fContext);
2100     ok(wirecf->u.dwValue == cf, "Marshaled value should be 0x%04x instead of 0x%04x\n", cf, wirecf->u.dwValue);
2101     ok(!memcmp(wirecf+1, cf_marshaled, sizeof(cf_marshaled)), "Marshaled data differs\n");
2102
2103     CLIPFORMAT_UserUnmarshal(&flags, buffer, &cf2);
2104     ok(cf == cf2, "Didn't unmarshal properly\n");
2105     HeapFree(GetProcessHeap(), 0, buffer);
2106
2107     CLIPFORMAT_UserFree(&flags, &cf2);
2108 }
2109
2110 static void test_marshal_HWND(void)
2111 {
2112     unsigned char *buffer;
2113     ULONG size;
2114     ULONG flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2115     HWND hwnd = GetDesktopWindow();
2116     HWND hwnd2;
2117     wireHWND wirehwnd;
2118
2119     size = HWND_UserSize(&flags, 0, &hwnd);
2120     ok(size == sizeof(*wirehwnd), "Wrong size %d\n", size);
2121
2122     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2123     HWND_UserMarshal(&flags, buffer, &hwnd);
2124     wirehwnd = (wireHWND)buffer;
2125     ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext);
2126     ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote);
2127
2128     HWND_UserUnmarshal(&flags, buffer, &hwnd2);
2129     ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
2130     HeapFree(GetProcessHeap(), 0, buffer);
2131
2132     HWND_UserFree(&flags, &hwnd2);
2133 }
2134
2135 static void test_marshal_HGLOBAL(void)
2136 {
2137     unsigned char *buffer;
2138     ULONG size;
2139     ULONG flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2140     HGLOBAL hglobal;
2141     HGLOBAL hglobal2;
2142     unsigned char *wirehglobal;
2143     int i;
2144
2145     hglobal = NULL;
2146     flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2147     size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2148     /* native is poorly programmed and allocates 4 bytes more than it needs to
2149      * here - Wine doesn't have to emulate that */
2150     ok((size == 8) || (size == 12), "Size should be 12, instead of %d\n", size);
2151     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2152     HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2153     wirehglobal = buffer;
2154     ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
2155     wirehglobal += sizeof(ULONG);
2156     ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+4 should be HGLOBAL\n");
2157     HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2158     ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
2159     HeapFree(GetProcessHeap(), 0, buffer);
2160     HGLOBAL_UserFree(&flags, &hglobal2);
2161
2162     hglobal = GlobalAlloc(0, 4);
2163     buffer = GlobalLock(hglobal);
2164     for (i = 0; i < 4; i++)
2165         buffer[i] = i;
2166     GlobalUnlock(hglobal);
2167     flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2168     size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2169     /* native is poorly programmed and allocates 4 bytes more than it needs to
2170      * here - Wine doesn't have to emulate that */
2171     ok((size == 24) || (size == 28), "Size should be 24 or 28, instead of %d\n", size);
2172     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2173     HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2174     wirehglobal = buffer;
2175     ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
2176     wirehglobal += sizeof(ULONG);
2177     ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0x4 should be HGLOBAL\n");
2178     wirehglobal += sizeof(ULONG);
2179     ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL\n");
2180     wirehglobal += sizeof(ULONG);
2181     ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0xc should be HGLOBAL\n");
2182     wirehglobal += sizeof(ULONG);
2183     ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL\n");
2184     wirehglobal += sizeof(ULONG);
2185     for (i = 0; i < 4; i++)
2186         ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
2187     HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2188     ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
2189     HeapFree(GetProcessHeap(), 0, buffer);
2190     HGLOBAL_UserFree(&flags, &hglobal2);
2191     GlobalFree(hglobal);
2192 }
2193
2194 static HENHMETAFILE create_emf(void)
2195 {
2196     RECT rect = {0, 0, 100, 100};
2197     HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
2198     ExtTextOut(hdc, 0, 0, ETO_OPAQUE, NULL, "Test String", strlen("Test String"), NULL);
2199     return CloseEnhMetaFile(hdc);
2200 }
2201
2202 static void test_marshal_HENHMETAFILE(void)
2203 {
2204     unsigned char *buffer;
2205     ULONG size;
2206     ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2207     HENHMETAFILE hemf;
2208     HENHMETAFILE hemf2 = NULL;
2209     unsigned char *wirehemf;
2210
2211     hemf = create_emf();
2212
2213     size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2214     ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
2215     buffer = HeapAlloc(GetProcessHeap(), 0, size);
2216     HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2217     wirehemf = buffer;
2218     ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
2219     wirehemf += sizeof(DWORD);
2220     ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
2221     wirehemf += sizeof(DWORD);
2222     ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
2223     wirehemf += sizeof(DWORD);
2224     ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
2225     wirehemf += sizeof(DWORD);
2226     ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD *)wirehemf);
2227     wirehemf += sizeof(DWORD);
2228     /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
2229      * at this point */
2230
2231     HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2232     ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
2233     HeapFree(GetProcessHeap(), 0, buffer);
2234     HENHMETAFILE_UserFree(&flags, &hemf2);
2235     DeleteEnhMetaFile(hemf);
2236
2237     /* test NULL emf */
2238     hemf = NULL;
2239
2240     size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2241     ok(size == 8, "size should be 8 bytes, not %d\n", size);
2242     buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
2243     HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2244     wirehemf = buffer;
2245     ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
2246     wirehemf += sizeof(DWORD);
2247     ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
2248     wirehemf += sizeof(DWORD);
2249
2250     HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2251     ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
2252     HeapFree(GetProcessHeap(), 0, buffer);
2253     HENHMETAFILE_UserFree(&flags, &hemf2);
2254 }
2255
2256 static void test_CoGetInterfaceAndReleaseStream(void)
2257 {
2258     HRESULT hr;
2259     IUnknown *pUnk;
2260
2261     hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
2262     ok(hr == E_INVALIDARG, "hr %08x\n", hr);
2263 }
2264
2265 START_TEST(marshal)
2266 {
2267     WNDCLASS wndclass;
2268     HMODULE hOle32 = GetModuleHandle("ole32");
2269     if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
2270
2271     /* register a window class used in several tests */
2272     memset(&wndclass, 0, sizeof(wndclass));
2273     wndclass.lpfnWndProc = window_proc;
2274     wndclass.lpszClassName = "WineCOMTest";
2275     RegisterClass(&wndclass);
2276
2277     test_cocreateinstance_proxy();
2278
2279     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2280
2281     /* FIXME: test CoCreateInstanceEx */
2282
2283     /* lifecycle management and marshaling tests */
2284     test_no_marshaler();
2285     test_normal_marshal_and_release();
2286     test_normal_marshal_and_unmarshal();
2287     test_marshal_and_unmarshal_invalid();
2288     test_interthread_marshal_and_unmarshal();
2289     test_proxy_marshal_and_unmarshal();
2290     test_proxy_marshal_and_unmarshal2();
2291     test_marshal_stub_apartment_shutdown();
2292     test_marshal_proxy_apartment_shutdown();
2293     test_marshal_proxy_mta_apartment_shutdown();
2294     test_no_couninitialize_server();
2295     test_no_couninitialize_client();
2296     test_tableweak_marshal_and_unmarshal_twice();
2297     test_tableweak_marshal_releasedata1();
2298     test_tableweak_marshal_releasedata2();
2299     test_tablestrong_marshal_and_unmarshal_twice();
2300     test_lock_object_external();
2301     test_disconnect_stub();
2302     test_normal_marshal_and_unmarshal_twice();
2303     test_hresult_marshaling();
2304     test_proxy_used_in_wrong_thread();
2305     test_message_filter();
2306     test_bad_marshal_stream();
2307     test_proxy_interfaces();
2308     test_stubbuffer(&IID_IClassFactory);
2309     test_proxybuffer(&IID_IClassFactory);
2310     test_message_reentrancy();
2311     test_WM_QUIT_handling();
2312     test_freethreadedmarshaler();
2313
2314     /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
2315     if (0) test_out_of_process_com();
2316
2317     test_ROT();
2318     test_globalinterfacetable();
2319
2320     test_marshal_CLIPFORMAT();
2321     test_marshal_HWND();
2322     test_marshal_HGLOBAL();
2323     test_marshal_HENHMETAFILE();
2324
2325     test_CoGetInterfaceAndReleaseStream();
2326
2327     CoUninitialize();
2328     return;
2329
2330 no_test:
2331     trace("You need DCOM95 installed to run this test\n");
2332     return;
2333 }