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