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