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