user32: Delay registration of the builtin classes until the first window is created.
[wine.git] / dlls / ole32 / tests / marshal.c
blob09ba030ad999e4bb825f1beafbe0c99224b998c5
1 /*
2 * Marshaling Tests
4 * Copyright 2004 Robert Shearman
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.
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.
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
21 #define _WIN32_DCOM
22 #define COBJMACROS
23 #define CONST_VTABLE
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31 #include "olectl.h"
32 #include "shlguid.h"
33 #include "shobjidl.h"
34 #include "initguid.h"
36 #include "wine/test.h"
38 DEFINE_GUID(CLSID_StdGlobalInterfaceTable,0x00000323,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
39 DEFINE_GUID(CLSID_ManualResetEvent, 0x0000032c,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
41 /* functions that are not present on all versions of Windows */
42 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
43 static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID,REFIID,LPVOID);
45 /* helper macros to make tests a bit leaner */
46 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
47 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
48 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
50 static const IID IID_IWineTest =
52 0x5201163f,
53 0x8164,
54 0x4fd0,
55 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
56 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
58 static const IID IID_IRemUnknown =
60 0x00000131,
61 0x0000,
62 0x0000,
63 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
66 #define EXTENTID_WineTest IID_IWineTest
67 #define CLSID_WineTest IID_IWineTest
69 static const CLSID CLSID_WineOOPTest =
71 0x5201163f,
72 0x8164,
73 0x4fd0,
74 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
75 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
77 static void test_cocreateinstance_proxy(void)
79 IUnknown *pProxy;
80 IMultiQI *pMQI;
81 HRESULT hr;
83 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
85 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
86 ok_ole_success(hr, CoCreateInstance);
87 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
88 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
89 if (hr == S_OK)
90 IMultiQI_Release(pMQI);
91 IUnknown_Release(pProxy);
93 CoUninitialize();
96 static const LARGE_INTEGER ullZero;
97 static LONG cLocks;
99 static void LockModule(void)
101 InterlockedIncrement(&cLocks);
104 static void UnlockModule(void)
106 InterlockedDecrement(&cLocks);
110 static HRESULT WINAPI Test_IUnknown_QueryInterface(
111 LPUNKNOWN iface,
112 REFIID riid,
113 LPVOID *ppvObj)
115 if (ppvObj == NULL) return E_POINTER;
117 if (IsEqualGUID(riid, &IID_IUnknown))
119 *ppvObj = iface;
120 IUnknown_AddRef(iface);
121 return S_OK;
124 *ppvObj = NULL;
125 return E_NOINTERFACE;
128 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
130 LockModule();
131 return 2; /* non-heap-based object */
134 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
136 UnlockModule();
137 return 1; /* non-heap-based object */
140 static const IUnknownVtbl TestUnknown_Vtbl =
142 Test_IUnknown_QueryInterface,
143 Test_IUnknown_AddRef,
144 Test_IUnknown_Release,
147 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
150 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
151 LPCLASSFACTORY iface,
152 REFIID riid,
153 LPVOID *ppvObj)
155 if (ppvObj == NULL) return E_POINTER;
157 if (IsEqualGUID(riid, &IID_IUnknown) ||
158 IsEqualGUID(riid, &IID_IClassFactory) ||
159 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
160 IsEqualGUID(riid, &IID_IRemUnknown))
162 *ppvObj = iface;
163 IClassFactory_AddRef(iface);
164 return S_OK;
167 *ppvObj = NULL;
168 return E_NOINTERFACE;
171 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
173 LockModule();
174 return 2; /* non-heap-based object */
177 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
179 UnlockModule();
180 return 1; /* non-heap-based object */
183 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
184 LPCLASSFACTORY iface,
185 LPUNKNOWN pUnkOuter,
186 REFIID riid,
187 LPVOID *ppvObj)
189 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
190 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
193 static HRESULT WINAPI Test_IClassFactory_LockServer(
194 LPCLASSFACTORY iface,
195 BOOL fLock)
197 return S_OK;
200 static const IClassFactoryVtbl TestClassFactory_Vtbl =
202 Test_IClassFactory_QueryInterface,
203 Test_IClassFactory_AddRef,
204 Test_IClassFactory_Release,
205 Test_IClassFactory_CreateInstance,
206 Test_IClassFactory_LockServer
209 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
211 #define RELEASEMARSHALDATA WM_USER
213 struct host_object_data
215 IStream *stream;
216 IID iid;
217 IUnknown *object;
218 MSHLFLAGS marshal_flags;
219 HANDLE marshal_event;
220 IMessageFilter *filter;
223 static DWORD CALLBACK host_object_proc(LPVOID p)
225 struct host_object_data *data = p;
226 HRESULT hr;
227 MSG msg;
229 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
231 if (data->filter)
233 IMessageFilter * prev_filter = NULL;
234 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
235 if (prev_filter) IMessageFilter_Release(prev_filter);
236 ok_ole_success(hr, CoRegisterMessageFilter);
239 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
240 ok_ole_success(hr, CoMarshalInterface);
242 /* force the message queue to be created before signaling parent thread */
243 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
245 SetEvent(data->marshal_event);
247 while (GetMessageA(&msg, NULL, 0, 0))
249 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
251 CoReleaseMarshalData(data->stream);
252 SetEvent((HANDLE)msg.lParam);
254 else
255 DispatchMessageA(&msg);
258 HeapFree(GetProcessHeap(), 0, data);
260 CoUninitialize();
262 return hr;
265 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
267 DWORD tid = 0;
268 HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
269 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
271 data->stream = stream;
272 data->iid = *riid;
273 data->object = object;
274 data->marshal_flags = marshal_flags;
275 data->marshal_event = marshal_event;
276 data->filter = filter;
278 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
280 /* wait for marshaling to complete before returning */
281 ok( !WaitForSingleObject(marshal_event, 10000), "wait timed out\n" );
282 CloseHandle(marshal_event);
284 return tid;
287 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
289 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
292 /* asks thread to release the marshal data because it has to be done by the
293 * same thread that marshaled the interface in the first place. */
294 static void release_host_object(DWORD tid)
296 HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
297 PostThreadMessageA(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
298 ok( !WaitForSingleObject(event, 10000), "wait timed out\n" );
299 CloseHandle(event);
302 static void end_host_object(DWORD tid, HANDLE thread)
304 BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
305 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
306 /* be careful of races - don't return until hosting thread has terminated */
307 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
308 CloseHandle(thread);
311 /* tests failure case of interface not having a marshaler specified in the
312 * registry */
313 static void test_no_marshaler(void)
315 IStream *pStream;
316 HRESULT hr;
318 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
319 ok_ole_success(hr, CreateStreamOnHGlobal);
320 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
321 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
323 IStream_Release(pStream);
326 /* tests normal marshal and then release without unmarshaling */
327 static void test_normal_marshal_and_release(void)
329 HRESULT hr;
330 IStream *pStream = NULL;
332 cLocks = 0;
334 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
335 ok_ole_success(hr, CreateStreamOnHGlobal);
336 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
337 ok_ole_success(hr, CoMarshalInterface);
339 ok_more_than_one_lock();
341 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
342 hr = CoReleaseMarshalData(pStream);
343 ok_ole_success(hr, CoReleaseMarshalData);
344 IStream_Release(pStream);
346 ok_no_locks();
349 /* tests success case of a same-thread marshal and unmarshal */
350 static void test_normal_marshal_and_unmarshal(void)
352 HRESULT hr;
353 IStream *pStream = NULL;
354 IUnknown *pProxy = NULL;
356 cLocks = 0;
358 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
359 ok_ole_success(hr, CreateStreamOnHGlobal);
360 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
361 ok_ole_success(hr, CoMarshalInterface);
363 ok_more_than_one_lock();
365 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
366 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
367 ok_ole_success(hr, CoUnmarshalInterface);
368 IStream_Release(pStream);
370 ok_more_than_one_lock();
372 IUnknown_Release(pProxy);
374 ok_no_locks();
377 /* tests failure case of unmarshaling a freed object */
378 static void test_marshal_and_unmarshal_invalid(void)
380 HRESULT hr;
381 IStream *pStream = NULL;
382 IClassFactory *pProxy = NULL;
383 DWORD tid;
384 void * dummy;
385 HANDLE thread;
387 cLocks = 0;
389 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
390 ok_ole_success(hr, CreateStreamOnHGlobal);
391 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
393 ok_more_than_one_lock();
395 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
396 hr = CoReleaseMarshalData(pStream);
397 ok_ole_success(hr, CoReleaseMarshalData);
399 ok_no_locks();
401 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
402 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
403 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
405 ok_no_locks();
407 if (pProxy)
409 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
410 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
412 IClassFactory_Release(pProxy);
415 IStream_Release(pStream);
417 end_host_object(tid, thread);
420 static void test_same_apartment_unmarshal_failure(void)
422 HRESULT hr;
423 IStream *pStream;
424 IUnknown *pProxy;
425 static const LARGE_INTEGER llZero;
427 cLocks = 0;
429 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
430 ok_ole_success(hr, CreateStreamOnHGlobal);
432 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
433 ok_ole_success(hr, CoMarshalInterface);
435 ok_more_than_one_lock();
437 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
438 ok_ole_success(hr, IStream_Seek);
440 hr = CoUnmarshalInterface(pStream, &IID_IParseDisplayName, (void **)&pProxy);
441 ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
443 ok_no_locks();
445 IStream_Release(pStream);
448 /* tests success case of an interthread marshal */
449 static void test_interthread_marshal_and_unmarshal(void)
451 HRESULT hr;
452 IStream *pStream = NULL;
453 IUnknown *pProxy = NULL;
454 DWORD tid;
455 HANDLE thread;
457 cLocks = 0;
459 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
460 ok_ole_success(hr, CreateStreamOnHGlobal);
461 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
463 ok_more_than_one_lock();
465 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
466 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
467 ok_ole_success(hr, CoUnmarshalInterface);
468 IStream_Release(pStream);
470 ok_more_than_one_lock();
472 IUnknown_Release(pProxy);
474 ok_no_locks();
476 end_host_object(tid, thread);
479 /* the number of external references that Wine's proxy manager normally gives
480 * out, so we can test the border case of running out of references */
481 #define NORMALEXTREFS 5
483 /* tests success case of an interthread marshal and then marshaling the proxy */
484 static void test_proxy_marshal_and_unmarshal(void)
486 HRESULT hr;
487 IStream *pStream = NULL;
488 IUnknown *pProxy = NULL;
489 IUnknown *pProxy2 = NULL;
490 DWORD tid;
491 HANDLE thread;
492 int i;
494 cLocks = 0;
496 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
497 ok_ole_success(hr, CreateStreamOnHGlobal);
498 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
500 ok_more_than_one_lock();
502 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
503 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
504 ok_ole_success(hr, CoUnmarshalInterface);
506 ok_more_than_one_lock();
508 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
509 /* marshal the proxy */
510 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
511 ok_ole_success(hr, CoMarshalInterface);
513 ok_more_than_one_lock();
515 /* marshal 5 more times to exhaust the normal external references of 5 */
516 for (i = 0; i < NORMALEXTREFS; i++)
518 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
519 ok_ole_success(hr, CoMarshalInterface);
522 ok_more_than_one_lock();
524 /* release the original proxy to test that we successfully keep the
525 * original object alive */
526 IUnknown_Release(pProxy);
528 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
529 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
530 ok_ole_success(hr, CoUnmarshalInterface);
532 ok_more_than_one_lock();
534 IUnknown_Release(pProxy2);
536 /* unmarshal all of the proxies to check that the object stub still exists */
537 for (i = 0; i < NORMALEXTREFS; i++)
539 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
540 ok_ole_success(hr, CoUnmarshalInterface);
542 IUnknown_Release(pProxy2);
545 ok_no_locks();
547 IStream_Release(pStream);
549 end_host_object(tid, thread);
552 /* tests success case of an interthread marshal and then marshaling the proxy
553 * using an iid that hasn't previously been unmarshaled */
554 static void test_proxy_marshal_and_unmarshal2(void)
556 HRESULT hr;
557 IStream *pStream = NULL;
558 IUnknown *pProxy = NULL;
559 IUnknown *pProxy2 = NULL;
560 DWORD tid;
561 HANDLE thread;
563 cLocks = 0;
565 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
566 ok_ole_success(hr, CreateStreamOnHGlobal);
567 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
569 ok_more_than_one_lock();
571 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
572 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
573 ok_ole_success(hr, CoUnmarshalInterface);
575 ok_more_than_one_lock();
577 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
578 /* marshal the proxy */
579 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
580 ok_ole_success(hr, CoMarshalInterface);
582 ok_more_than_one_lock();
584 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
585 /* unmarshal the second proxy to the object */
586 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
587 ok_ole_success(hr, CoUnmarshalInterface);
588 IStream_Release(pStream);
590 /* now the proxies should be as follows:
591 * pProxy -> &Test_ClassFactory
592 * pProxy2 -> &Test_ClassFactory
593 * they should NOT be as follows:
594 * pProxy -> &Test_ClassFactory
595 * pProxy2 -> pProxy
596 * the above can only really be tested by looking in +ole traces
599 ok_more_than_one_lock();
601 IUnknown_Release(pProxy);
603 ok_more_than_one_lock();
605 IUnknown_Release(pProxy2);
607 ok_no_locks();
609 end_host_object(tid, thread);
612 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
613 static void test_proxy_marshal_and_unmarshal_weak(void)
615 HRESULT hr;
616 IStream *pStream = NULL;
617 IUnknown *pProxy = NULL;
618 IUnknown *pProxy2 = NULL;
619 DWORD tid;
620 HANDLE thread;
622 cLocks = 0;
624 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
625 ok_ole_success(hr, CreateStreamOnHGlobal);
626 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
628 ok_more_than_one_lock();
630 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
631 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
632 ok_ole_success(hr, CoUnmarshalInterface);
634 ok_more_than_one_lock();
636 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
637 /* marshal the proxy */
638 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
639 ok_ole_success(hr, CoMarshalInterface);
641 ok_more_than_one_lock();
643 /* release the original proxy to test that we successfully keep the
644 * original object alive */
645 IUnknown_Release(pProxy);
647 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
648 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
649 todo_wine
650 ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr);
652 ok_no_locks();
654 IStream_Release(pStream);
656 end_host_object(tid, thread);
659 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
660 static void test_proxy_marshal_and_unmarshal_strong(void)
662 HRESULT hr;
663 IStream *pStream = NULL;
664 IUnknown *pProxy = NULL;
665 IUnknown *pProxy2 = NULL;
666 DWORD tid;
667 HANDLE thread;
669 cLocks = 0;
671 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
672 ok_ole_success(hr, CreateStreamOnHGlobal);
673 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
675 ok_more_than_one_lock();
677 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
678 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
679 ok_ole_success(hr, CoUnmarshalInterface);
681 ok_more_than_one_lock();
683 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
684 /* marshal the proxy */
685 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
686 ok(hr == S_OK /* WinNT */ || hr == E_INVALIDARG /* Win9x */,
687 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr);
688 if (FAILED(hr))
690 IUnknown_Release(pProxy);
691 goto end;
694 ok_more_than_one_lock();
696 /* release the original proxy to test that we successfully keep the
697 * original object alive */
698 IUnknown_Release(pProxy);
700 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
701 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
702 ok_ole_success(hr, CoUnmarshalInterface);
704 ok_more_than_one_lock();
706 IUnknown_Release(pProxy2);
708 ok_more_than_one_lock();
710 end:
711 IStream_Release(pStream);
713 end_host_object(tid, thread);
715 ok_no_locks();
718 /* tests that stubs are released when the containing apartment is destroyed */
719 static void test_marshal_stub_apartment_shutdown(void)
721 HRESULT hr;
722 IStream *pStream = NULL;
723 IUnknown *pProxy = NULL;
724 DWORD tid;
725 HANDLE thread;
727 cLocks = 0;
729 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
730 ok_ole_success(hr, CreateStreamOnHGlobal);
731 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
733 ok_more_than_one_lock();
735 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
736 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
737 ok_ole_success(hr, CoUnmarshalInterface);
738 IStream_Release(pStream);
740 ok_more_than_one_lock();
742 end_host_object(tid, thread);
744 ok_no_locks();
746 IUnknown_Release(pProxy);
748 ok_no_locks();
751 /* tests that proxies are released when the containing apartment is destroyed */
752 static void test_marshal_proxy_apartment_shutdown(void)
754 HRESULT hr;
755 IStream *pStream = NULL;
756 IUnknown *pProxy = NULL;
757 DWORD tid;
758 HANDLE thread;
760 cLocks = 0;
762 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
763 ok_ole_success(hr, CreateStreamOnHGlobal);
764 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
766 ok_more_than_one_lock();
768 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
769 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
770 ok_ole_success(hr, CoUnmarshalInterface);
771 IStream_Release(pStream);
773 ok_more_than_one_lock();
775 CoUninitialize();
777 ok_no_locks();
779 IUnknown_Release(pProxy);
781 ok_no_locks();
783 end_host_object(tid, thread);
785 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
788 /* tests that proxies are released when the containing mta apartment is destroyed */
789 static void test_marshal_proxy_mta_apartment_shutdown(void)
791 HRESULT hr;
792 IStream *pStream = NULL;
793 IUnknown *pProxy = NULL;
794 DWORD tid;
795 HANDLE thread;
797 CoUninitialize();
798 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
800 cLocks = 0;
802 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
803 ok_ole_success(hr, CreateStreamOnHGlobal);
804 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
806 ok_more_than_one_lock();
808 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
809 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
810 ok_ole_success(hr, CoUnmarshalInterface);
811 IStream_Release(pStream);
813 ok_more_than_one_lock();
815 CoUninitialize();
817 ok_no_locks();
819 IUnknown_Release(pProxy);
821 ok_no_locks();
823 end_host_object(tid, thread);
825 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
828 struct ncu_params
830 LPSTREAM stream;
831 HANDLE marshal_event;
832 HANDLE unmarshal_event;
835 /* helper for test_no_couninitialize_server */
836 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
838 struct ncu_params *ncu_params = p;
839 HRESULT hr;
841 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
843 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
844 ok_ole_success(hr, CoMarshalInterface);
846 SetEvent(ncu_params->marshal_event);
848 ok( !WaitForSingleObject(ncu_params->unmarshal_event, 10000), "wait timed out\n" );
850 /* die without calling CoUninitialize */
852 return 0;
855 /* tests apartment that an apartment with a stub is released without deadlock
856 * if the owning thread exits */
857 static void test_no_couninitialize_server(void)
859 HRESULT hr;
860 IStream *pStream = NULL;
861 IUnknown *pProxy = NULL;
862 DWORD tid;
863 HANDLE thread;
864 struct ncu_params ncu_params;
866 cLocks = 0;
868 ncu_params.marshal_event = CreateEventA(NULL, TRUE, FALSE, NULL);
869 ncu_params.unmarshal_event = CreateEventA(NULL, TRUE, FALSE, NULL);
871 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
872 ok_ole_success(hr, CreateStreamOnHGlobal);
873 ncu_params.stream = pStream;
875 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
877 ok( !WaitForSingleObject(ncu_params.marshal_event, 10000), "wait timed out\n" );
878 ok_more_than_one_lock();
880 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
881 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
882 ok_ole_success(hr, CoUnmarshalInterface);
883 IStream_Release(pStream);
885 ok_more_than_one_lock();
887 SetEvent(ncu_params.unmarshal_event);
888 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
890 ok_no_locks();
892 CloseHandle(thread);
893 CloseHandle(ncu_params.marshal_event);
894 CloseHandle(ncu_params.unmarshal_event);
896 IUnknown_Release(pProxy);
898 ok_no_locks();
901 /* STA -> STA call during DLL_THREAD_DETACH */
902 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
904 struct ncu_params *ncu_params = p;
905 HRESULT hr;
906 IUnknown *pProxy = NULL;
908 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
910 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
911 ok_ole_success(hr, CoUnmarshalInterface);
912 IStream_Release(ncu_params->stream);
914 ok_more_than_one_lock();
916 /* die without calling CoUninitialize */
918 return 0;
921 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
922 static void test_no_couninitialize_client(void)
924 HRESULT hr;
925 IStream *pStream = NULL;
926 DWORD tid;
927 DWORD host_tid;
928 HANDLE thread;
929 HANDLE host_thread;
930 struct ncu_params ncu_params;
932 cLocks = 0;
934 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
935 ok_ole_success(hr, CreateStreamOnHGlobal);
936 ncu_params.stream = pStream;
938 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
939 * always deadlock when called from within DllMain */
940 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
941 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
943 ok_more_than_one_lock();
945 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
947 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
948 CloseHandle(thread);
950 ok_no_locks();
952 end_host_object(host_tid, host_thread);
955 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
956 static void test_tableweak_marshal_and_unmarshal_twice(void)
958 HRESULT hr;
959 IStream *pStream = NULL;
960 IUnknown *pProxy1 = NULL;
961 IUnknown *pProxy2 = NULL;
962 DWORD tid;
963 HANDLE thread;
965 cLocks = 0;
967 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
968 ok_ole_success(hr, CreateStreamOnHGlobal);
969 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
971 ok_more_than_one_lock();
973 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
974 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
975 ok_ole_success(hr, CoUnmarshalInterface);
977 ok_more_than_one_lock();
979 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
980 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
981 IStream_Release(pStream);
982 ok_ole_success(hr, CoUnmarshalInterface);
984 ok_more_than_one_lock();
986 IUnknown_Release(pProxy1);
987 IUnknown_Release(pProxy2);
989 /* this line is shows the difference between weak and strong table marshaling:
990 * weak has cLocks == 0
991 * strong has cLocks > 0 */
992 ok_no_locks();
994 end_host_object(tid, thread);
997 /* tests releasing after unmarshaling one object */
998 static void test_tableweak_marshal_releasedata1(void)
1000 HRESULT hr;
1001 IStream *pStream = NULL;
1002 IUnknown *pProxy1 = NULL;
1003 IUnknown *pProxy2 = NULL;
1004 DWORD tid;
1005 HANDLE thread;
1007 cLocks = 0;
1009 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1010 ok_ole_success(hr, CreateStreamOnHGlobal);
1011 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1013 ok_more_than_one_lock();
1015 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1016 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1017 ok_ole_success(hr, CoUnmarshalInterface);
1019 ok_more_than_one_lock();
1021 /* release the remaining reference on the object by calling
1022 * CoReleaseMarshalData in the hosting thread */
1023 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1024 release_host_object(tid);
1026 ok_more_than_one_lock();
1028 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1029 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1030 ok_ole_success(hr, CoUnmarshalInterface);
1031 IStream_Release(pStream);
1033 ok_more_than_one_lock();
1035 IUnknown_Release(pProxy1);
1036 if (pProxy2)
1037 IUnknown_Release(pProxy2);
1039 /* this line is shows the difference between weak and strong table marshaling:
1040 * weak has cLocks == 0
1041 * strong has cLocks > 0 */
1042 ok_no_locks();
1044 end_host_object(tid, thread);
1047 /* tests releasing after unmarshaling one object */
1048 static void test_tableweak_marshal_releasedata2(void)
1050 HRESULT hr;
1051 IStream *pStream = NULL;
1052 IUnknown *pProxy = NULL;
1053 DWORD tid;
1054 HANDLE thread;
1056 cLocks = 0;
1058 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1059 ok_ole_success(hr, CreateStreamOnHGlobal);
1060 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1062 ok_more_than_one_lock();
1064 /* release the remaining reference on the object by calling
1065 * CoReleaseMarshalData in the hosting thread */
1066 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1067 release_host_object(tid);
1069 ok_no_locks();
1071 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1072 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1073 todo_wine
1075 ok(hr == CO_E_OBJNOTREG,
1076 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1077 hr);
1079 IStream_Release(pStream);
1081 ok_no_locks();
1083 end_host_object(tid, thread);
1086 struct weak_and_normal_marshal_data
1088 IStream *pStreamWeak;
1089 IStream *pStreamNormal;
1090 HANDLE hReadyEvent;
1091 HANDLE hQuitEvent;
1094 static DWORD CALLBACK weak_and_normal_marshal_thread_proc(void *p)
1096 HRESULT hr;
1097 struct weak_and_normal_marshal_data *data = p;
1098 HANDLE hQuitEvent = data->hQuitEvent;
1099 MSG msg;
1101 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1103 hr = CoMarshalInterface(data->pStreamWeak, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
1104 ok_ole_success(hr, "CoMarshalInterface");
1106 hr = CoMarshalInterface(data->pStreamNormal, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1107 ok_ole_success(hr, "CoMarshalInterface");
1109 /* force the message queue to be created before signaling parent thread */
1110 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
1112 SetEvent(data->hReadyEvent);
1114 while (WAIT_OBJECT_0 + 1 == MsgWaitForMultipleObjects(1, &hQuitEvent, FALSE, 10000, QS_ALLINPUT))
1116 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1117 DispatchMessageA(&msg);
1119 CloseHandle(hQuitEvent);
1121 CoUninitialize();
1123 return 0;
1126 /* tests interaction between table-weak and normal marshalling of an object */
1127 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
1129 HRESULT hr;
1130 IUnknown *pProxyWeak = NULL;
1131 IUnknown *pProxyNormal = NULL;
1132 DWORD tid;
1133 HANDLE thread;
1134 struct weak_and_normal_marshal_data data;
1136 cLocks = 0;
1138 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
1139 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
1140 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStreamWeak);
1141 ok_ole_success(hr, CreateStreamOnHGlobal);
1142 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStreamNormal);
1143 ok_ole_success(hr, CreateStreamOnHGlobal);
1145 thread = CreateThread(NULL, 0, weak_and_normal_marshal_thread_proc, &data, 0, &tid);
1146 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
1147 CloseHandle(data.hReadyEvent);
1149 ok_more_than_one_lock();
1151 IStream_Seek(data.pStreamWeak, ullZero, STREAM_SEEK_SET, NULL);
1152 hr = CoUnmarshalInterface(data.pStreamWeak, &IID_IClassFactory, (void **)&pProxyWeak);
1153 ok_ole_success(hr, CoUnmarshalInterface);
1155 ok_more_than_one_lock();
1157 IStream_Seek(data.pStreamNormal, ullZero, STREAM_SEEK_SET, NULL);
1158 hr = CoUnmarshalInterface(data.pStreamNormal, &IID_IClassFactory, (void **)&pProxyNormal);
1159 ok_ole_success(hr, CoUnmarshalInterface);
1161 ok_more_than_one_lock();
1163 IUnknown_Release(pProxyNormal);
1165 ok_more_than_one_lock();
1167 IUnknown_Release(pProxyWeak);
1169 ok_no_locks();
1171 IStream_Release(data.pStreamWeak);
1172 IStream_Release(data.pStreamNormal);
1174 SetEvent(data.hQuitEvent);
1175 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1176 CloseHandle(thread);
1179 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
1180 static void test_tablestrong_marshal_and_unmarshal_twice(void)
1182 HRESULT hr;
1183 IStream *pStream = NULL;
1184 IUnknown *pProxy1 = NULL;
1185 IUnknown *pProxy2 = NULL;
1186 DWORD tid;
1187 HANDLE thread;
1189 cLocks = 0;
1191 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1192 ok_ole_success(hr, CreateStreamOnHGlobal);
1193 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
1195 ok_more_than_one_lock();
1197 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1198 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1199 ok_ole_success(hr, CoUnmarshalInterface);
1201 ok_more_than_one_lock();
1203 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1204 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1205 ok_ole_success(hr, CoUnmarshalInterface);
1207 ok_more_than_one_lock();
1209 if (pProxy1) IUnknown_Release(pProxy1);
1210 if (pProxy2) IUnknown_Release(pProxy2);
1212 /* this line is shows the difference between weak and strong table marshaling:
1213 * weak has cLocks == 0
1214 * strong has cLocks > 0 */
1215 ok_more_than_one_lock();
1217 /* release the remaining reference on the object by calling
1218 * CoReleaseMarshalData in the hosting thread */
1219 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1220 release_host_object(tid);
1221 IStream_Release(pStream);
1223 ok_no_locks();
1225 end_host_object(tid, thread);
1228 /* tests CoLockObjectExternal */
1229 static void test_lock_object_external(void)
1231 HRESULT hr;
1232 IStream *pStream = NULL;
1234 cLocks = 0;
1236 /* test the stub manager creation aspect of CoLockObjectExternal when the
1237 * object hasn't been marshaled yet */
1238 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1240 ok_more_than_one_lock();
1242 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1244 ok_no_locks();
1246 /* test our empty stub manager being handled correctly in
1247 * CoMarshalInterface */
1248 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1250 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1251 ok_ole_success(hr, CreateStreamOnHGlobal);
1252 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1253 ok_ole_success(hr, CoMarshalInterface);
1255 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1257 ok_more_than_one_lock();
1259 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1260 hr = CoReleaseMarshalData(pStream);
1261 ok_ole_success(hr, CoReleaseMarshalData);
1262 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1264 ok_more_than_one_lock();
1266 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1268 ok_more_than_one_lock();
1270 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1272 ok_no_locks();
1274 /* test CoLockObjectExternal releases reference to object with
1275 * fLastUnlockReleases as TRUE and there are only strong references on
1276 * the object */
1277 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE);
1279 ok_more_than_one_lock();
1281 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE);
1283 ok_no_locks();
1285 /* test CoLockObjectExternal doesn't release the last reference to an
1286 * object with fLastUnlockReleases as TRUE and there is a weak reference
1287 * on the object */
1288 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
1289 ok_ole_success(hr, CoMarshalInterface);
1291 ok_more_than_one_lock();
1293 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE);
1295 ok_more_than_one_lock();
1297 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE);
1299 ok_more_than_one_lock();
1301 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1303 ok_no_locks();
1305 IStream_Release(pStream);
1308 /* tests disconnecting stubs */
1309 static void test_disconnect_stub(void)
1311 HRESULT hr;
1312 IStream *pStream = NULL;
1314 cLocks = 0;
1316 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1317 ok_ole_success(hr, CreateStreamOnHGlobal);
1318 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1319 ok_ole_success(hr, CoMarshalInterface);
1321 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1323 ok_more_than_one_lock();
1325 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1326 hr = CoReleaseMarshalData(pStream);
1327 ok_ole_success(hr, CoReleaseMarshalData);
1328 IStream_Release(pStream);
1330 ok_more_than_one_lock();
1332 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1334 ok_no_locks();
1336 hr = CoDisconnectObject(NULL, 0);
1337 ok( hr == E_INVALIDARG, "wrong status %x\n", hr );
1340 /* tests failure case of a same-thread marshal and unmarshal twice */
1341 static void test_normal_marshal_and_unmarshal_twice(void)
1343 HRESULT hr;
1344 IStream *pStream = NULL;
1345 IUnknown *pProxy1 = NULL;
1346 IUnknown *pProxy2 = NULL;
1348 cLocks = 0;
1350 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1351 ok_ole_success(hr, CreateStreamOnHGlobal);
1352 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1353 ok_ole_success(hr, CoMarshalInterface);
1355 ok_more_than_one_lock();
1357 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1358 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1359 ok_ole_success(hr, CoUnmarshalInterface);
1361 ok_more_than_one_lock();
1363 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1364 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1365 ok(hr == CO_E_OBJNOTCONNECTED,
1366 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
1368 IStream_Release(pStream);
1370 ok_more_than_one_lock();
1372 IUnknown_Release(pProxy1);
1374 ok_no_locks();
1377 /* tests success case of marshaling and unmarshaling an HRESULT */
1378 static void test_hresult_marshaling(void)
1380 HRESULT hr;
1381 HRESULT hr_marshaled = 0;
1382 IStream *pStream = NULL;
1383 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1385 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1386 ok_ole_success(hr, CreateStreamOnHGlobal);
1388 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1389 ok_ole_success(hr, CoMarshalHresult);
1391 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1392 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1393 ok_ole_success(hr, IStream_Read);
1395 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1397 hr_marshaled = 0;
1398 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1399 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1400 ok_ole_success(hr, CoUnmarshalHresult);
1402 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1404 IStream_Release(pStream);
1408 /* helper for test_proxy_used_in_wrong_thread */
1409 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1411 IClassFactory * cf = p;
1412 HRESULT hr;
1413 IUnknown * proxy = NULL;
1415 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1416 todo_wine
1417 ok(hr == CO_E_NOTINITIALIZED,
1418 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
1419 hr);
1421 hr = IClassFactory_QueryInterface(cf, &IID_IMultiQI, (LPVOID *)&proxy);
1422 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
1423 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr);
1424 if (SUCCEEDED(hr))
1425 IUnknown_Release(proxy);
1427 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
1428 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1429 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr);
1430 if (SUCCEEDED(hr))
1431 IUnknown_Release(proxy);
1433 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1435 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1436 if (proxy) IUnknown_Release(proxy);
1437 ok(hr == RPC_E_WRONG_THREAD,
1438 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1439 hr);
1441 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
1442 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1443 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr);
1445 /* now be really bad and release the proxy from the wrong apartment */
1446 IClassFactory_Release(cf);
1448 CoUninitialize();
1450 return 0;
1453 /* tests failure case of a using a proxy in the wrong apartment */
1454 static void test_proxy_used_in_wrong_thread(void)
1456 HRESULT hr;
1457 IStream *pStream = NULL;
1458 IUnknown *pProxy = NULL;
1459 DWORD tid, tid2;
1460 HANDLE thread;
1461 HANDLE host_thread;
1463 cLocks = 0;
1465 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1466 ok_ole_success(hr, CreateStreamOnHGlobal);
1467 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1469 ok_more_than_one_lock();
1471 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1472 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1473 ok_ole_success(hr, CoUnmarshalInterface);
1474 IStream_Release(pStream);
1476 ok_more_than_one_lock();
1478 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
1479 IUnknown_QueryInterface(pProxy, &IID_IStream, (LPVOID *)&pStream);
1481 /* create a thread that we can misbehave in */
1482 thread = CreateThread(NULL, 0, bad_thread_proc, pProxy, 0, &tid2);
1484 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1485 CloseHandle(thread);
1487 /* do release statement on Win9x that we should have done above */
1488 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
1489 IUnknown_Release(pProxy);
1491 ok_no_locks();
1493 end_host_object(tid, host_thread);
1496 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1498 if (ppvObj == NULL) return E_POINTER;
1500 if (IsEqualGUID(riid, &IID_IUnknown) ||
1501 IsEqualGUID(riid, &IID_IClassFactory))
1503 *ppvObj = iface;
1504 IMessageFilter_AddRef(iface);
1505 return S_OK;
1508 return E_NOINTERFACE;
1511 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1513 return 2; /* non-heap object */
1516 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1518 return 1; /* non-heap object */
1521 static DWORD WINAPI MessageFilter_HandleInComingCall(
1522 IMessageFilter *iface,
1523 DWORD dwCallType,
1524 HTASK threadIDCaller,
1525 DWORD dwTickCount,
1526 LPINTERFACEINFO lpInterfaceInfo)
1528 static int callcount = 0;
1529 DWORD ret;
1530 trace("HandleInComingCall\n");
1531 switch (callcount)
1533 case 0:
1534 ret = SERVERCALL_REJECTED;
1535 break;
1536 case 1:
1537 ret = SERVERCALL_RETRYLATER;
1538 break;
1539 default:
1540 ret = SERVERCALL_ISHANDLED;
1541 break;
1543 callcount++;
1544 return ret;
1547 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1548 IMessageFilter *iface,
1549 HTASK threadIDCallee,
1550 DWORD dwTickCount,
1551 DWORD dwRejectType)
1553 trace("RetryRejectedCall\n");
1554 return 0;
1557 static DWORD WINAPI MessageFilter_MessagePending(
1558 IMessageFilter *iface,
1559 HTASK threadIDCallee,
1560 DWORD dwTickCount,
1561 DWORD dwPendingType)
1563 trace("MessagePending\n");
1564 return PENDINGMSG_WAITNOPROCESS;
1567 static const IMessageFilterVtbl MessageFilter_Vtbl =
1569 MessageFilter_QueryInterface,
1570 MessageFilter_AddRef,
1571 MessageFilter_Release,
1572 MessageFilter_HandleInComingCall,
1573 MessageFilter_RetryRejectedCall,
1574 MessageFilter_MessagePending
1577 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1579 static void test_message_filter(void)
1581 HRESULT hr;
1582 IStream *pStream = NULL;
1583 IClassFactory *cf = NULL;
1584 DWORD tid;
1585 IUnknown *proxy = NULL;
1586 IMessageFilter *prev_filter = NULL;
1587 HANDLE thread;
1589 cLocks = 0;
1591 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1592 ok_ole_success(hr, CreateStreamOnHGlobal);
1593 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1595 ok_more_than_one_lock();
1597 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1598 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1599 ok_ole_success(hr, CoUnmarshalInterface);
1600 IStream_Release(pStream);
1602 ok_more_than_one_lock();
1604 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1605 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr);
1606 if (proxy) IUnknown_Release(proxy);
1607 proxy = NULL;
1609 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1610 ok_ole_success(hr, CoRegisterMessageFilter);
1612 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1613 ok_ole_success(hr, IClassFactory_CreateInstance);
1615 IUnknown_Release(proxy);
1617 IClassFactory_Release(cf);
1619 ok_no_locks();
1621 end_host_object(tid, thread);
1623 hr = CoRegisterMessageFilter(prev_filter, NULL);
1624 ok_ole_success(hr, CoRegisterMessageFilter);
1627 /* test failure case of trying to unmarshal from bad stream */
1628 static void test_bad_marshal_stream(void)
1630 HRESULT hr;
1631 IStream *pStream = NULL;
1633 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1634 ok_ole_success(hr, CreateStreamOnHGlobal);
1635 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1636 ok_ole_success(hr, CoMarshalInterface);
1638 ok_more_than_one_lock();
1640 /* try to read beyond end of stream */
1641 hr = CoReleaseMarshalData(pStream);
1642 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
1644 /* now release for real */
1645 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1646 hr = CoReleaseMarshalData(pStream);
1647 ok_ole_success(hr, CoReleaseMarshalData);
1649 IStream_Release(pStream);
1652 /* tests that proxies implement certain interfaces */
1653 static void test_proxy_interfaces(void)
1655 HRESULT hr;
1656 IStream *pStream = NULL;
1657 IUnknown *pProxy = NULL;
1658 IUnknown *pOtherUnknown = NULL;
1659 DWORD tid;
1660 HANDLE thread;
1662 cLocks = 0;
1664 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1665 ok_ole_success(hr, CreateStreamOnHGlobal);
1666 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1668 ok_more_than_one_lock();
1670 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1671 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1672 ok_ole_success(hr, CoUnmarshalInterface);
1673 IStream_Release(pStream);
1675 ok_more_than_one_lock();
1677 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1678 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1679 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1681 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1682 ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity);
1683 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1685 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1686 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1687 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1689 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1690 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1691 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1693 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1694 * useless as it has no more methods over IMarshal that it inherits from. */
1696 IUnknown_Release(pProxy);
1698 ok_no_locks();
1700 end_host_object(tid, thread);
1703 typedef struct
1705 IUnknown IUnknown_iface;
1706 ULONG refs;
1707 } HeapUnknown;
1709 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
1711 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
1714 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1716 if (IsEqualIID(riid, &IID_IUnknown))
1718 IUnknown_AddRef(iface);
1719 *ppv = iface;
1720 return S_OK;
1722 *ppv = NULL;
1723 return E_NOINTERFACE;
1726 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1728 HeapUnknown *This = impl_from_IUnknown(iface);
1729 return InterlockedIncrement((LONG*)&This->refs);
1732 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1734 HeapUnknown *This = impl_from_IUnknown(iface);
1735 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1736 if (!refs) HeapFree(GetProcessHeap(), 0, This);
1737 return refs;
1740 static const IUnknownVtbl HeapUnknown_Vtbl =
1742 HeapUnknown_QueryInterface,
1743 HeapUnknown_AddRef,
1744 HeapUnknown_Release
1747 static void test_proxybuffer(REFIID riid)
1749 HRESULT hr;
1750 IPSFactoryBuffer *psfb;
1751 IRpcProxyBuffer *proxy;
1752 LPVOID lpvtbl;
1753 ULONG refs;
1754 CLSID clsid;
1755 HeapUnknown *pUnkOuter = HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1757 pUnkOuter->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1758 pUnkOuter->refs = 1;
1760 hr = CoGetPSClsid(riid, &clsid);
1761 ok_ole_success(hr, CoGetPSClsid);
1763 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1764 ok_ole_success(hr, CoGetClassObject);
1766 hr = IPSFactoryBuffer_CreateProxy(psfb, &pUnkOuter->IUnknown_iface, riid, &proxy, &lpvtbl);
1767 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1768 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1770 /* release our reference to the outer unknown object - the PS factory
1771 * buffer will have AddRef's it in the CreateProxy call */
1772 refs = IUnknown_Release(&pUnkOuter->IUnknown_iface);
1773 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
1775 /* Not checking return, unreliable on native. Maybe it leaks references? */
1776 IPSFactoryBuffer_Release(psfb);
1778 refs = IUnknown_Release((IUnknown *)lpvtbl);
1779 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1781 refs = IRpcProxyBuffer_Release(proxy);
1782 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1785 static void test_stubbuffer(REFIID riid)
1787 HRESULT hr;
1788 IPSFactoryBuffer *psfb;
1789 IRpcStubBuffer *stub;
1790 ULONG refs;
1791 CLSID clsid;
1793 cLocks = 0;
1795 hr = CoGetPSClsid(riid, &clsid);
1796 ok_ole_success(hr, CoGetPSClsid);
1798 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1799 ok_ole_success(hr, CoGetClassObject);
1801 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1802 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1804 /* Not checking return, unreliable on native. Maybe it leaks references? */
1805 IPSFactoryBuffer_Release(psfb);
1807 ok_more_than_one_lock();
1809 IRpcStubBuffer_Disconnect(stub);
1811 ok_no_locks();
1813 refs = IRpcStubBuffer_Release(stub);
1814 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1817 static HWND hwnd_app;
1819 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1820 LPCLASSFACTORY iface,
1821 LPUNKNOWN pUnkOuter,
1822 REFIID riid,
1823 LPVOID *ppvObj)
1825 DWORD_PTR res;
1826 if (IsEqualIID(riid, &IID_IWineTest))
1828 BOOL ret = SendMessageTimeoutA(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1829 ok(ret, "Timed out sending a message to originating window during RPC call\n");
1831 *ppvObj = NULL;
1832 return S_FALSE;
1835 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1837 Test_IClassFactory_QueryInterface,
1838 Test_IClassFactory_AddRef,
1839 Test_IClassFactory_Release,
1840 TestRE_IClassFactory_CreateInstance,
1841 Test_IClassFactory_LockServer
1844 static IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1846 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1848 switch (msg)
1850 case WM_USER:
1852 HRESULT hr;
1853 IStream *pStream = NULL;
1854 IClassFactory *proxy = NULL;
1855 IUnknown *object;
1856 DWORD tid;
1857 HANDLE thread;
1859 cLocks = 0;
1861 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1862 ok_ole_success(hr, CreateStreamOnHGlobal);
1863 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1865 ok_more_than_one_lock();
1867 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1868 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1869 ok_ole_success(hr, CoReleaseMarshalData);
1870 IStream_Release(pStream);
1872 ok_more_than_one_lock();
1874 /* note the use of the magic IID_IWineTest value to tell remote thread
1875 * to try to send a message back to us */
1876 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1877 ok(hr == S_FALSE, "expected S_FALSE, got %d\n", hr);
1879 IClassFactory_Release(proxy);
1881 ok_no_locks();
1883 end_host_object(tid, thread);
1885 PostMessageA(hwnd, WM_QUIT, 0, 0);
1887 return 0;
1889 case WM_USER+1:
1891 HRESULT hr;
1892 IStream *pStream = NULL;
1893 IClassFactory *proxy = NULL;
1894 IUnknown *object;
1895 DWORD tid;
1896 HANDLE thread;
1898 cLocks = 0;
1900 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1901 ok_ole_success(hr, CreateStreamOnHGlobal);
1902 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1904 ok_more_than_one_lock();
1906 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1907 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1908 ok_ole_success(hr, CoReleaseMarshalData);
1909 IStream_Release(pStream);
1911 ok_more_than_one_lock();
1913 /* post quit message before a doing a COM call to show that a pending
1914 * WM_QUIT message doesn't stop the call from succeeding */
1915 PostMessageA(hwnd, WM_QUIT, 0, 0);
1916 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1917 ok(hr == S_FALSE, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr);
1919 IClassFactory_Release(proxy);
1921 ok_no_locks();
1923 end_host_object(tid, thread);
1925 return 0;
1927 case WM_USER+2:
1929 HRESULT hr;
1930 IStream *pStream = NULL;
1931 IClassFactory *proxy = NULL;
1932 IUnknown *object;
1933 DWORD tid;
1934 HANDLE thread;
1936 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1937 ok_ole_success(hr, CreateStreamOnHGlobal);
1938 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1940 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1941 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1942 ok_ole_success(hr, CoReleaseMarshalData);
1943 IStream_Release(pStream);
1945 /* shows that COM calls executed during the processing of sent
1946 * messages should fail */
1947 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1948 ok(hr == RPC_E_CANTCALLOUT_ININPUTSYNCCALL,
1949 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr);
1951 IClassFactory_Release(proxy);
1953 end_host_object(tid, thread);
1955 PostQuitMessage(0);
1957 return 0;
1959 default:
1960 return DefWindowProcA(hwnd, msg, wparam, lparam);
1964 static void register_test_window(void)
1966 WNDCLASSA wndclass;
1968 memset(&wndclass, 0, sizeof(wndclass));
1969 wndclass.lpfnWndProc = window_proc;
1970 wndclass.lpszClassName = "WineCOMTest";
1971 RegisterClassA(&wndclass);
1974 static void test_message_reentrancy(void)
1976 MSG msg;
1978 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1979 ok(hwnd_app != NULL, "Window creation failed\n");
1981 /* start message re-entrancy test */
1982 PostMessageA(hwnd_app, WM_USER, 0, 0);
1984 while (GetMessageA(&msg, NULL, 0, 0))
1986 TranslateMessage(&msg);
1987 DispatchMessageA(&msg);
1989 DestroyWindow(hwnd_app);
1992 static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance(
1993 LPCLASSFACTORY iface,
1994 LPUNKNOWN pUnkOuter,
1995 REFIID riid,
1996 LPVOID *ppvObj)
1998 *ppvObj = NULL;
1999 SendMessageA(hwnd_app, WM_USER+2, 0, 0);
2000 return S_OK;
2003 static IClassFactoryVtbl TestMsgClassFactory_Vtbl =
2005 Test_IClassFactory_QueryInterface,
2006 Test_IClassFactory_AddRef,
2007 Test_IClassFactory_Release,
2008 TestMsg_IClassFactory_CreateInstance,
2009 Test_IClassFactory_LockServer
2012 static IClassFactory TestMsg_ClassFactory = { &TestMsgClassFactory_Vtbl };
2014 static void test_call_from_message(void)
2016 MSG msg;
2017 IStream *pStream;
2018 HRESULT hr;
2019 IClassFactory *proxy;
2020 DWORD tid;
2021 HANDLE thread;
2022 IUnknown *object;
2024 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
2025 ok(hwnd_app != NULL, "Window creation failed\n");
2027 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2028 ok_ole_success(hr, CreateStreamOnHGlobal);
2029 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2031 ok_more_than_one_lock();
2033 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2034 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2035 ok_ole_success(hr, CoReleaseMarshalData);
2036 IStream_Release(pStream);
2038 ok_more_than_one_lock();
2040 /* start message re-entrancy test */
2041 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
2042 ok_ole_success(hr, IClassFactory_CreateInstance);
2044 IClassFactory_Release(proxy);
2046 ok_no_locks();
2048 end_host_object(tid, thread);
2050 while (GetMessageA(&msg, NULL, 0, 0))
2052 TranslateMessage(&msg);
2053 DispatchMessageA(&msg);
2055 DestroyWindow(hwnd_app);
2058 static void test_WM_QUIT_handling(void)
2060 MSG msg;
2062 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
2063 ok(hwnd_app != NULL, "Window creation failed\n");
2065 /* start WM_QUIT handling test */
2066 PostMessageA(hwnd_app, WM_USER+1, 0, 0);
2068 while (GetMessageA(&msg, NULL, 0, 0))
2070 TranslateMessage(&msg);
2071 DispatchMessageA(&msg);
2075 static SIZE_T round_global_size(SIZE_T size)
2077 static SIZE_T global_size_alignment = -1;
2078 if (global_size_alignment == -1)
2080 void *p = GlobalAlloc(GMEM_FIXED, 1);
2081 global_size_alignment = GlobalSize(p);
2082 GlobalFree(p);
2085 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
2088 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
2090 HGLOBAL hglobal;
2091 DWORD size;
2092 char *marshal_data;
2093 HRESULT hr;
2095 hr = GetHGlobalFromStream(pStream, &hglobal);
2096 ok_ole_success(hr, GetHGlobalFromStream);
2098 size = GlobalSize(hglobal);
2100 marshal_data = GlobalLock(hglobal);
2102 if (mshctx == MSHCTX_INPROC)
2104 DWORD expected_size = round_global_size(3*sizeof(DWORD) + sizeof(GUID));
2105 ok(size == expected_size ||
2106 broken(size == (2*sizeof(DWORD))) /* Win9x & NT4 */,
2107 "size should have been %d instead of %d\n", expected_size, size);
2109 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
2110 marshal_data += sizeof(DWORD);
2111 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
2112 marshal_data += sizeof(void *);
2113 if (sizeof(void*) == 4 && size >= 3*sizeof(DWORD))
2115 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
2116 marshal_data += sizeof(DWORD);
2118 if (size >= 3*sizeof(DWORD) + sizeof(GUID))
2120 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
2121 ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
2122 ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
2123 ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
2126 else
2128 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
2129 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
2130 "marshal data should be filled by standard marshal and start with MEOW signature\n");
2133 GlobalUnlock(hglobal);
2136 static void test_freethreadedmarshaler(void)
2138 HRESULT hr;
2139 IUnknown *pFTUnknown;
2140 IMarshal *pFTMarshal;
2141 IStream *pStream;
2142 IUnknown *pProxy;
2143 static const LARGE_INTEGER llZero;
2145 cLocks = 0;
2146 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
2147 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
2148 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
2149 ok_ole_success(hr, IUnknown_QueryInterface);
2150 IUnknown_Release(pFTUnknown);
2152 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2153 ok_ole_success(hr, CreateStreamOnHGlobal);
2155 /* inproc normal marshaling */
2157 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
2158 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2159 ok_ole_success(hr, IMarshal_MarshalInterface);
2161 ok_more_than_one_lock();
2163 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
2165 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2166 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
2167 ok_ole_success(hr, IMarshal_UnmarshalInterface);
2169 IUnknown_Release(pProxy);
2171 ok_no_locks();
2173 /* native doesn't allow us to unmarshal or release the stream data,
2174 * presumably because it wants us to call CoMarshalInterface instead */
2175 if (0)
2177 /* local normal marshaling */
2179 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2180 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
2181 ok_ole_success(hr, IMarshal_MarshalInterface);
2183 ok_more_than_one_lock();
2185 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
2187 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2188 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
2189 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
2191 ok_no_locks();
2194 /* inproc table-strong marshaling */
2196 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2197 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
2198 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
2199 MSHLFLAGS_TABLESTRONG);
2200 ok_ole_success(hr, IMarshal_MarshalInterface);
2202 ok_more_than_one_lock();
2204 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
2206 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2207 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
2208 ok_ole_success(hr, IMarshal_UnmarshalInterface);
2210 IUnknown_Release(pProxy);
2212 ok_more_than_one_lock();
2214 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2215 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
2216 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
2218 ok_no_locks();
2220 /* inproc table-weak marshaling */
2222 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2223 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
2224 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
2225 MSHLFLAGS_TABLEWEAK);
2226 ok_ole_success(hr, IMarshal_MarshalInterface);
2228 ok_no_locks();
2230 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
2232 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2233 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
2234 ok_ole_success(hr, IMarshal_UnmarshalInterface);
2236 ok_more_than_one_lock();
2238 IUnknown_Release(pProxy);
2240 ok_no_locks();
2242 /* inproc normal marshaling (for extraordinary cases) */
2244 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2245 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
2246 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2247 ok_ole_success(hr, IMarshal_MarshalInterface);
2249 ok_more_than_one_lock();
2251 /* this call shows that DisconnectObject does nothing */
2252 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
2253 ok_ole_success(hr, IMarshal_DisconnectObject);
2255 ok_more_than_one_lock();
2257 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2258 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
2259 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
2261 ok_no_locks();
2263 /* doesn't enforce marshaling rules here and allows us to unmarshal the
2264 * interface, even though it was freed above */
2265 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2266 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
2267 ok_ole_success(hr, IMarshal_UnmarshalInterface);
2269 ok_no_locks();
2271 IStream_Release(pStream);
2272 IMarshal_Release(pFTMarshal);
2275 static HRESULT reg_unreg_wine_test_class(BOOL Register)
2277 HRESULT hr;
2278 char buffer[256];
2279 LPOLESTR pszClsid;
2280 HKEY hkey;
2281 DWORD dwDisposition;
2282 DWORD error;
2284 hr = StringFromCLSID(&CLSID_WineTest, &pszClsid);
2285 ok_ole_success(hr, "StringFromCLSID");
2286 strcpy(buffer, "CLSID\\");
2287 WideCharToMultiByte(CP_ACP, 0, pszClsid, -1, buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), NULL, NULL);
2288 CoTaskMemFree(pszClsid);
2289 strcat(buffer, "\\InprocHandler32");
2290 if (Register)
2292 error = RegCreateKeyExA(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition);
2293 if (error == ERROR_ACCESS_DENIED)
2295 skip("Not authorized to modify the Classes key\n");
2296 return E_FAIL;
2298 ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error);
2299 if (error != ERROR_SUCCESS) hr = E_FAIL;
2300 error = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
2301 ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error);
2302 if (error != ERROR_SUCCESS) hr = E_FAIL;
2303 RegCloseKey(hkey);
2305 else
2307 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer);
2308 *strrchr(buffer, '\\') = '\0';
2309 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer);
2311 return hr;
2314 static void test_inproc_handler(void)
2316 HRESULT hr;
2317 IUnknown *pObject;
2318 IUnknown *pObject2;
2320 if (FAILED(reg_unreg_wine_test_class(TRUE)))
2321 return;
2323 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pObject);
2324 ok_ole_success(hr, "CoCreateInstance");
2326 if (SUCCEEDED(hr))
2328 hr = IUnknown_QueryInterface(pObject, &IID_IWineTest, (void **)&pObject2);
2329 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr);
2331 /* it's a handler as it supports IOleObject */
2332 hr = IUnknown_QueryInterface(pObject, &IID_IOleObject, (void **)&pObject2);
2333 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
2334 IUnknown_Release(pObject2);
2336 IUnknown_Release(pObject);
2339 reg_unreg_wine_test_class(FALSE);
2342 static HRESULT WINAPI Test_SMI_QueryInterface(
2343 IStdMarshalInfo *iface,
2344 REFIID riid,
2345 LPVOID *ppvObj)
2347 if (ppvObj == NULL) return E_POINTER;
2349 if (IsEqualGUID(riid, &IID_IUnknown) ||
2350 IsEqualGUID(riid, &IID_IStdMarshalInfo))
2352 *ppvObj = iface;
2353 IStdMarshalInfo_AddRef(iface);
2354 return S_OK;
2357 return E_NOINTERFACE;
2360 static ULONG WINAPI Test_SMI_AddRef(IStdMarshalInfo *iface)
2362 LockModule();
2363 return 2; /* non-heap-based object */
2366 static ULONG WINAPI Test_SMI_Release(IStdMarshalInfo *iface)
2368 UnlockModule();
2369 return 1; /* non-heap-based object */
2372 static HRESULT WINAPI Test_SMI_GetClassForHandler(
2373 IStdMarshalInfo *iface,
2374 DWORD dwDestContext,
2375 void *pvDestContext,
2376 CLSID *pClsid)
2378 *pClsid = CLSID_WineTest;
2379 return S_OK;
2382 static const IStdMarshalInfoVtbl Test_SMI_Vtbl =
2384 Test_SMI_QueryInterface,
2385 Test_SMI_AddRef,
2386 Test_SMI_Release,
2387 Test_SMI_GetClassForHandler
2390 static IStdMarshalInfo Test_SMI = {&Test_SMI_Vtbl};
2392 static void test_handler_marshaling(void)
2394 HRESULT hr;
2395 IStream *pStream = NULL;
2396 IUnknown *pProxy = NULL;
2397 IUnknown *pObject;
2398 DWORD tid;
2399 HANDLE thread;
2400 static const LARGE_INTEGER ullZero;
2402 if (FAILED(reg_unreg_wine_test_class(TRUE)))
2403 return;
2404 cLocks = 0;
2406 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2407 ok_ole_success(hr, "CreateStreamOnHGlobal");
2408 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_SMI, MSHLFLAGS_NORMAL, &thread);
2410 ok_more_than_one_lock();
2412 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2413 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
2414 ok_ole_success(hr, "CoUnmarshalInterface");
2415 IStream_Release(pStream);
2417 if(hr == S_OK)
2419 ok_more_than_one_lock();
2421 hr = IUnknown_QueryInterface(pProxy, &IID_IWineTest, (void **)&pObject);
2422 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2424 /* it's a handler as it supports IOleObject */
2425 hr = IUnknown_QueryInterface(pProxy, &IID_IOleObject, (void **)&pObject);
2426 todo_wine
2427 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
2428 if (SUCCEEDED(hr)) IUnknown_Release(pObject);
2430 IUnknown_Release(pProxy);
2432 ok_no_locks();
2435 end_host_object(tid, thread);
2436 reg_unreg_wine_test_class(FALSE);
2438 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2442 static void test_client_security(void)
2444 HRESULT hr;
2445 IStream *pStream = NULL;
2446 IClassFactory *pProxy = NULL;
2447 IUnknown *pProxy2 = NULL;
2448 IUnknown *pUnknown1 = NULL;
2449 IUnknown *pUnknown2 = NULL;
2450 IClientSecurity *pCliSec = NULL;
2451 IMarshal *pMarshal;
2452 DWORD tid;
2453 HANDLE thread;
2454 static const LARGE_INTEGER ullZero;
2455 DWORD dwAuthnSvc;
2456 DWORD dwAuthzSvc;
2457 OLECHAR *pServerPrincName;
2458 DWORD dwAuthnLevel;
2459 DWORD dwImpLevel;
2460 void *pAuthInfo;
2461 DWORD dwCapabilities;
2462 void *pv;
2464 cLocks = 0;
2466 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2467 ok_ole_success(hr, "CreateStreamOnHGlobal");
2468 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2470 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2471 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
2472 ok_ole_success(hr, "CoUnmarshalInterface");
2473 IStream_Release(pStream);
2475 hr = IClassFactory_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pUnknown1);
2476 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
2478 hr = IClassFactory_QueryInterface(pProxy, &IID_IRemUnknown, (LPVOID*)&pProxy2);
2479 ok_ole_success(hr, "IUnknown_QueryInterface IID_IStream");
2481 hr = IUnknown_QueryInterface(pProxy2, &IID_IUnknown, (LPVOID*)&pUnknown2);
2482 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
2484 ok(pUnknown1 == pUnknown2, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1, pUnknown2);
2486 hr = IClassFactory_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pMarshal);
2487 ok_ole_success(hr, "IUnknown_QueryInterface IID_IMarshal");
2489 hr = IClassFactory_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pCliSec);
2490 ok_ole_success(hr, "IUnknown_QueryInterface IID_IClientSecurity");
2492 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2493 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket (all NULLs)");
2495 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pMarshal, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2496 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2498 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
2499 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket");
2501 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthInfo, dwCapabilities);
2502 todo_wine ok_ole_success(hr, "IClientSecurity_SetBlanket");
2504 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IWineTest, &pv);
2505 ok(hr == E_NOINTERFACE, "COM call should have succeeded instead of returning 0x%08x\n", hr);
2507 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pMarshal, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
2508 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2510 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, 0xdeadbeef, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
2511 todo_wine ok(hr == E_INVALIDARG, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
2513 CoTaskMemFree(pServerPrincName);
2515 hr = IClientSecurity_QueryBlanket(pCliSec, pUnknown1, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
2516 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket(IUnknown)");
2518 CoTaskMemFree(pServerPrincName);
2520 IClassFactory_Release(pProxy);
2521 IUnknown_Release(pProxy2);
2522 IUnknown_Release(pUnknown1);
2523 IUnknown_Release(pUnknown2);
2524 IMarshal_Release(pMarshal);
2525 IClientSecurity_Release(pCliSec);
2527 end_host_object(tid, thread);
2530 static HANDLE heventShutdown;
2532 static void LockModuleOOP(void)
2534 InterlockedIncrement(&cLocks); /* for test purposes only */
2535 CoAddRefServerProcess();
2538 static void UnlockModuleOOP(void)
2540 InterlockedDecrement(&cLocks); /* for test purposes only */
2541 if (!CoReleaseServerProcess())
2542 SetEvent(heventShutdown);
2545 static HWND hwnd_app;
2547 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
2548 LPCLASSFACTORY iface,
2549 REFIID riid,
2550 LPVOID *ppvObj)
2552 if (ppvObj == NULL) return E_POINTER;
2554 if (IsEqualGUID(riid, &IID_IUnknown) ||
2555 IsEqualGUID(riid, &IID_IClassFactory))
2557 *ppvObj = iface;
2558 IClassFactory_AddRef(iface);
2559 return S_OK;
2562 return E_NOINTERFACE;
2565 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
2567 return 2; /* non-heap-based object */
2570 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
2572 return 1; /* non-heap-based object */
2575 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
2576 LPCLASSFACTORY iface,
2577 LPUNKNOWN pUnkOuter,
2578 REFIID riid,
2579 LPVOID *ppvObj)
2581 if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
2583 *ppvObj = iface;
2584 return S_OK;
2586 return CLASS_E_CLASSNOTAVAILABLE;
2589 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
2590 LPCLASSFACTORY iface,
2591 BOOL fLock)
2593 if (fLock)
2594 LockModuleOOP();
2595 else
2596 UnlockModuleOOP();
2597 return S_OK;
2600 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
2602 TestOOP_IClassFactory_QueryInterface,
2603 TestOOP_IClassFactory_AddRef,
2604 TestOOP_IClassFactory_Release,
2605 TestOOP_IClassFactory_CreateInstance,
2606 TestOOP_IClassFactory_LockServer
2609 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
2611 static void test_register_local_server(void)
2613 DWORD cookie;
2614 HRESULT hr;
2615 HANDLE ready_event;
2616 HANDLE quit_event;
2617 DWORD wait;
2619 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL);
2621 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2622 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
2623 ok_ole_success(hr, CoRegisterClassObject);
2625 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
2626 SetEvent(ready_event);
2628 quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
2632 wait = MsgWaitForMultipleObjects(1, &quit_event, FALSE, 30000, QS_ALLINPUT);
2633 if (wait == WAIT_OBJECT_0+1)
2635 MSG msg;
2637 if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
2639 trace("Message 0x%x\n", msg.message);
2640 TranslateMessage(&msg);
2641 DispatchMessageA(&msg);
2645 while (wait == WAIT_OBJECT_0+1);
2647 ok( wait == WAIT_OBJECT_0, "quit event wait timed out\n" );
2648 hr = CoRevokeClassObject(cookie);
2649 ok_ole_success(hr, CoRevokeClassObject);
2652 static HANDLE create_target_process(const char *arg)
2654 char **argv;
2655 char cmdline[MAX_PATH];
2656 BOOL ret;
2657 PROCESS_INFORMATION pi;
2658 STARTUPINFOA si = { 0 };
2659 si.cb = sizeof(si);
2661 pi.hThread = NULL;
2662 pi.hProcess = NULL;
2663 winetest_get_mainargs( &argv );
2664 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
2665 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2666 ok(ret, "CreateProcess failed with error: %u\n", GetLastError());
2667 if (pi.hThread) CloseHandle(pi.hThread);
2668 return pi.hProcess;
2671 /* tests functions commonly used by out of process COM servers */
2672 static void test_local_server(void)
2674 DWORD cookie;
2675 HRESULT hr;
2676 IClassFactory * cf;
2677 DWORD ret;
2678 HANDLE process;
2679 HANDLE quit_event;
2680 HANDLE ready_event;
2682 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL);
2684 cLocks = 0;
2686 /* Start the object suspended */
2687 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2688 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
2689 ok_ole_success(hr, CoRegisterClassObject);
2691 /* ... and CoGetClassObject does not find it and fails when it looks for the
2692 * class in the registry */
2693 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2694 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2695 ok(hr == REGDB_E_CLASSNOTREG || /* NT */
2696 hr == S_OK /* Win9x */,
2697 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2699 /* Resume the object suspended above ... */
2700 hr = CoResumeClassObjects();
2701 ok_ole_success(hr, CoResumeClassObjects);
2703 /* ... and now it should succeed */
2704 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2705 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2706 ok_ole_success(hr, CoGetClassObject);
2708 /* Now check the locking is working */
2709 /* NOTE: we are accessing the class directly, not through a proxy */
2711 ok_no_locks();
2713 hr = IClassFactory_LockServer(cf, TRUE);
2714 ok_ole_success(hr, IClassFactory_LockServer);
2716 ok_more_than_one_lock();
2718 IClassFactory_LockServer(cf, FALSE);
2719 ok_ole_success(hr, IClassFactory_LockServer);
2721 ok_no_locks();
2723 IClassFactory_Release(cf);
2725 /* wait for shutdown signal */
2726 ret = WaitForSingleObject(heventShutdown, 0);
2727 ok(ret != WAIT_TIMEOUT, "Server didn't shut down\n");
2729 /* try to connect again after SCM has suspended registered class objects */
2730 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
2731 &IID_IClassFactory, (LPVOID*)&cf);
2732 ok(hr == CO_E_SERVER_STOPPING || /* NT */
2733 hr == REGDB_E_CLASSNOTREG || /* win2k */
2734 hr == S_OK /* Win9x */,
2735 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2737 hr = CoRevokeClassObject(cookie);
2738 ok_ole_success(hr, CoRevokeClassObject);
2740 CloseHandle(heventShutdown);
2742 process = create_target_process("-Embedding");
2743 ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError());
2745 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
2746 ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" );
2747 CloseHandle(ready_event);
2749 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
2750 ok_ole_success(hr, CoCreateInstance);
2752 IClassFactory_Release(cf);
2754 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
2755 ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
2757 quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
2758 SetEvent(quit_event);
2760 winetest_wait_child_process( process );
2761 CloseHandle(quit_event);
2762 CloseHandle(process);
2765 struct git_params
2767 DWORD cookie;
2768 IGlobalInterfaceTable *git;
2771 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2773 HRESULT hr;
2774 struct git_params *params = pv;
2775 IClassFactory *cf;
2777 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2778 ok(hr == CO_E_NOTINITIALIZED ||
2779 broken(hr == E_UNEXPECTED) /* win2k */ ||
2780 broken(hr == S_OK) /* NT 4 */,
2781 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
2782 hr);
2783 if (hr == S_OK)
2784 IClassFactory_Release(cf);
2786 CoInitialize(NULL);
2788 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2789 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2791 IClassFactory_Release(cf);
2793 CoUninitialize();
2795 return hr;
2798 static void test_globalinterfacetable(void)
2800 HRESULT hr;
2801 IGlobalInterfaceTable *git;
2802 DWORD cookie;
2803 HANDLE thread;
2804 DWORD tid;
2805 struct git_params params;
2806 DWORD ret;
2807 IUnknown *object;
2808 IClassFactory *cf;
2809 ULONG ref;
2811 trace("test_globalinterfacetable\n");
2812 cLocks = 0;
2814 hr = pDllGetClassObject(&CLSID_StdGlobalInterfaceTable, &IID_IClassFactory, (void**)&cf);
2815 ok(hr == S_OK, "got 0x%08x\n", hr);
2817 hr = IClassFactory_QueryInterface(cf, &IID_IGlobalInterfaceTable, (void**)&object);
2818 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
2820 IClassFactory_Release(cf);
2822 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2823 ok_ole_success(hr, CoCreateInstance);
2825 ref = IGlobalInterfaceTable_AddRef(git);
2826 ok(ref == 1, "ref=%d\n", ref);
2827 ref = IGlobalInterfaceTable_AddRef(git);
2828 ok(ref == 1, "ref=%d\n", ref);
2830 ref = IGlobalInterfaceTable_Release(git);
2831 ok(ref == 1, "ref=%d\n", ref);
2832 ref = IGlobalInterfaceTable_Release(git);
2833 ok(ref == 1, "ref=%d\n", ref);
2835 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2836 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2838 ok_more_than_one_lock();
2840 params.cookie = cookie;
2841 params.git = git;
2842 /* note: params is on stack so we MUST wait for get_global_interface_proc
2843 * to exit before we can return */
2844 thread = CreateThread(NULL, 0, get_global_interface_proc, &params, 0, &tid);
2846 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT);
2847 while (ret == WAIT_OBJECT_0 + 1)
2849 MSG msg;
2850 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
2851 DispatchMessageA(&msg);
2852 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT);
2855 CloseHandle(thread);
2857 /* test getting interface from global with different iid */
2858 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IUnknown, (void **)&object);
2859 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2860 IUnknown_Release(object);
2862 /* test getting interface from global with same iid */
2863 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IClassFactory, (void **)&object);
2864 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2865 IUnknown_Release(object);
2867 hr = IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git, cookie);
2868 ok_ole_success(hr, IGlobalInterfaceTable_RevokeInterfaceFromGlobal);
2870 ok_no_locks();
2872 IGlobalInterfaceTable_Release(git);
2875 static void test_manualresetevent(void)
2877 ISynchronizeHandle *sync_handle;
2878 ISynchronize *psync1, *psync2;
2879 IUnknown *punk;
2880 HANDLE handle;
2881 LONG ref;
2882 HRESULT hr;
2884 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&punk);
2885 ok(hr == S_OK, "Got 0x%08x\n", hr);
2886 ok(!!punk, "Got NULL.\n");
2887 IUnknown_Release(punk);
2889 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync1);
2890 ok(hr == S_OK, "Got 0x%08x\n", hr);
2891 ok(!!psync1, "Got NULL.\n");
2893 hr = ISynchronize_Wait(psync1, 0, 5);
2894 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
2896 hr = ISynchronize_Reset(psync1);
2897 ok(hr == S_OK, "Got 0x%08x\n", hr);
2898 hr = ISynchronize_Signal(psync1);
2899 ok(hr == S_OK, "Got 0x%08x\n", hr);
2900 hr = ISynchronize_Wait(psync1, 0, 5);
2901 ok(hr == S_OK, "Got 0x%08x\n", hr);
2902 hr = ISynchronize_Wait(psync1, 0, 5);
2903 ok(hr == S_OK, "Got 0x%08x\n", hr);
2904 hr = ISynchronize_Reset(psync1);
2905 ok(hr == S_OK, "Got 0x%08x\n", hr);
2906 hr = ISynchronize_Wait(psync1, 0, 5);
2907 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
2909 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync2);
2910 ok(hr == S_OK, "Got 0x%08x\n", hr);
2911 ok(!!psync2, "Got NULL.\n");
2912 ok(psync1 != psync2, "psync1 == psync2.\n");
2914 hr = ISynchronize_QueryInterface(psync2, &IID_ISynchronizeHandle, (void**)&sync_handle);
2915 ok(hr == S_OK, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr);
2917 handle = NULL;
2918 hr = ISynchronizeHandle_GetHandle(sync_handle, &handle);
2919 ok(hr == S_OK, "GetHandle failed: %08x\n", hr);
2920 ok(handle != NULL && handle != INVALID_HANDLE_VALUE, "handle = %p\n", handle);
2922 ISynchronizeHandle_Release(sync_handle);
2924 hr = ISynchronize_Wait(psync2, 0, 5);
2925 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
2927 hr = ISynchronize_Reset(psync1);
2928 ok(hr == S_OK, "Got 0x%08x\n", hr);
2929 hr = ISynchronize_Reset(psync2);
2930 ok(hr == S_OK, "Got 0x%08x\n", hr);
2931 hr = ISynchronize_Signal(psync1);
2932 ok(hr == S_OK, "Got 0x%08x\n", hr);
2933 hr = ISynchronize_Wait(psync2, 0, 5);
2934 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
2936 ref = ISynchronize_AddRef(psync1);
2937 ok(ref == 2, "Got ref: %d\n", ref);
2938 ref = ISynchronize_AddRef(psync1);
2939 ok(ref == 3, "Got ref: %d\n", ref);
2940 ref = ISynchronize_Release(psync1);
2941 ok(ref == 2, "Got nonzero ref: %d\n", ref);
2942 ref = ISynchronize_Release(psync2);
2943 ok(!ref, "Got nonzero ref: %d\n", ref);
2944 ref = ISynchronize_Release(psync1);
2945 ok(ref == 1, "Got nonzero ref: %d\n", ref);
2946 ref = ISynchronize_Release(psync1);
2947 ok(!ref, "Got nonzero ref: %d\n", ref);
2950 static const char *debugstr_iid(REFIID riid)
2952 static char name[256];
2953 HKEY hkeyInterface;
2954 WCHAR bufferW[39];
2955 char buffer[39];
2956 LONG name_size = sizeof(name);
2957 StringFromGUID2(riid, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
2958 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
2959 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS)
2961 memcpy(name, buffer, sizeof(buffer));
2962 goto done;
2964 if (RegQueryValueA(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS)
2966 memcpy(name, buffer, sizeof(buffer));
2967 goto done;
2969 RegCloseKey(hkeyInterface);
2970 done:
2971 return name;
2974 static HRESULT WINAPI TestChannelHook_QueryInterface(IChannelHook *iface, REFIID riid, void **ppv)
2976 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IChannelHook))
2978 *ppv = iface;
2979 IChannelHook_AddRef(iface);
2980 return S_OK;
2983 *ppv = NULL;
2984 return E_NOINTERFACE;
2987 static ULONG WINAPI TestChannelHook_AddRef(IChannelHook *iface)
2989 return 2;
2992 static ULONG WINAPI TestChannelHook_Release(IChannelHook *iface)
2994 return 1;
2997 static void WINAPI TestChannelHook_ClientGetSize(
2998 IChannelHook *iface,
2999 REFGUID uExtent,
3000 REFIID riid,
3001 ULONG *pDataSize )
3003 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3004 trace("TestChannelHook_ClientGetBuffer\n");
3005 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
3006 trace("\tcid: %s\n", debugstr_iid(&info->uCausality));
3007 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3008 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3009 ok(!info->pObject, "info->pObject should be NULL\n");
3010 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3012 *pDataSize = 1;
3015 static void WINAPI TestChannelHook_ClientFillBuffer(
3016 IChannelHook *iface,
3017 REFGUID uExtent,
3018 REFIID riid,
3019 ULONG *pDataSize,
3020 void *pDataBuffer )
3022 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3023 trace("TestChannelHook_ClientFillBuffer\n");
3024 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3025 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3026 ok(!info->pObject, "info->pObject should be NULL\n");
3027 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3029 *(unsigned char *)pDataBuffer = 0xcc;
3030 *pDataSize = 1;
3033 static void WINAPI TestChannelHook_ClientNotify(
3034 IChannelHook *iface,
3035 REFGUID uExtent,
3036 REFIID riid,
3037 ULONG cbDataSize,
3038 void *pDataBuffer,
3039 DWORD lDataRep,
3040 HRESULT hrFault )
3042 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3043 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault);
3044 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3045 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3046 todo_wine {
3047 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
3049 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3052 static void WINAPI TestChannelHook_ServerNotify(
3053 IChannelHook *iface,
3054 REFGUID uExtent,
3055 REFIID riid,
3056 ULONG cbDataSize,
3057 void *pDataBuffer,
3058 DWORD lDataRep )
3060 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3061 trace("TestChannelHook_ServerNotify\n");
3062 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3063 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3064 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
3065 ok(cbDataSize == 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize);
3066 ok(*(unsigned char *)pDataBuffer == 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer);
3067 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3070 static void WINAPI TestChannelHook_ServerGetSize(
3071 IChannelHook *iface,
3072 REFGUID uExtent,
3073 REFIID riid,
3074 HRESULT hrFault,
3075 ULONG *pDataSize )
3077 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3078 trace("TestChannelHook_ServerGetSize\n");
3079 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
3080 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3081 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3082 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
3083 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3084 if (hrFault != S_OK)
3085 trace("\thrFault = 0x%08x\n", hrFault);
3087 *pDataSize = 0;
3090 static void WINAPI TestChannelHook_ServerFillBuffer(
3091 IChannelHook *iface,
3092 REFGUID uExtent,
3093 REFIID riid,
3094 ULONG *pDataSize,
3095 void *pDataBuffer,
3096 HRESULT hrFault )
3098 trace("TestChannelHook_ServerFillBuffer\n");
3099 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
3102 static const IChannelHookVtbl TestChannelHookVtbl =
3104 TestChannelHook_QueryInterface,
3105 TestChannelHook_AddRef,
3106 TestChannelHook_Release,
3107 TestChannelHook_ClientGetSize,
3108 TestChannelHook_ClientFillBuffer,
3109 TestChannelHook_ClientNotify,
3110 TestChannelHook_ServerNotify,
3111 TestChannelHook_ServerGetSize,
3112 TestChannelHook_ServerFillBuffer,
3115 static IChannelHook TestChannelHook = { &TestChannelHookVtbl };
3117 static void test_channel_hook(void)
3119 IStream *pStream = NULL;
3120 IClassFactory *cf = NULL;
3121 DWORD tid;
3122 IUnknown *proxy = NULL;
3123 HANDLE thread;
3124 HRESULT hr;
3126 hr = CoRegisterChannelHook(&EXTENTID_WineTest, &TestChannelHook);
3127 ok_ole_success(hr, CoRegisterChannelHook);
3129 hr = CoRegisterMessageFilter(&MessageFilter, NULL);
3130 ok_ole_success(hr, CoRegisterMessageFilter);
3132 cLocks = 0;
3134 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3135 ok_ole_success(hr, CreateStreamOnHGlobal);
3136 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
3138 ok_more_than_one_lock();
3140 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3141 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
3142 ok_ole_success(hr, CoUnmarshalInterface);
3143 IStream_Release(pStream);
3145 ok_more_than_one_lock();
3147 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
3148 ok_ole_success(hr, IClassFactory_CreateInstance);
3149 IUnknown_Release(proxy);
3151 IClassFactory_Release(cf);
3153 ok_no_locks();
3155 end_host_object(tid, thread);
3157 hr = CoRegisterMessageFilter(NULL, NULL);
3158 ok_ole_success(hr, CoRegisterMessageFilter);
3161 START_TEST(marshal)
3163 HMODULE hOle32 = GetModuleHandleA("ole32");
3164 int argc;
3165 char **argv;
3167 if (!GetProcAddress(hOle32, "CoRegisterSurrogateEx")) {
3168 win_skip("skipping test on win9x\n");
3169 return;
3172 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
3173 pDllGetClassObject = (void*)GetProcAddress(hOle32, "DllGetClassObject");
3175 argc = winetest_get_mainargs( &argv );
3176 if (argc > 2 && (!strcmp(argv[2], "-Embedding")))
3178 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3179 test_register_local_server();
3180 CoUninitialize();
3182 return;
3185 register_test_window();
3187 test_cocreateinstance_proxy();
3189 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3191 /* FIXME: test CoCreateInstanceEx */
3193 /* lifecycle management and marshaling tests */
3194 test_no_marshaler();
3195 test_normal_marshal_and_release();
3196 test_normal_marshal_and_unmarshal();
3197 test_marshal_and_unmarshal_invalid();
3198 test_same_apartment_unmarshal_failure();
3199 test_interthread_marshal_and_unmarshal();
3200 test_proxy_marshal_and_unmarshal();
3201 test_proxy_marshal_and_unmarshal2();
3202 test_proxy_marshal_and_unmarshal_weak();
3203 test_proxy_marshal_and_unmarshal_strong();
3204 test_marshal_stub_apartment_shutdown();
3205 test_marshal_proxy_apartment_shutdown();
3206 test_marshal_proxy_mta_apartment_shutdown();
3207 test_no_couninitialize_server();
3208 test_no_couninitialize_client();
3209 test_tableweak_marshal_and_unmarshal_twice();
3210 test_tableweak_marshal_releasedata1();
3211 test_tableweak_marshal_releasedata2();
3212 test_tableweak_and_normal_marshal_and_unmarshal();
3213 test_tablestrong_marshal_and_unmarshal_twice();
3214 test_lock_object_external();
3215 test_disconnect_stub();
3216 test_normal_marshal_and_unmarshal_twice();
3217 test_hresult_marshaling();
3218 test_proxy_used_in_wrong_thread();
3219 test_message_filter();
3220 test_bad_marshal_stream();
3221 test_proxy_interfaces();
3222 test_stubbuffer(&IID_IClassFactory);
3223 test_proxybuffer(&IID_IClassFactory);
3224 test_message_reentrancy();
3225 test_call_from_message();
3226 test_WM_QUIT_handling();
3227 test_freethreadedmarshaler();
3228 test_inproc_handler();
3229 test_handler_marshaling();
3230 test_client_security();
3232 test_local_server();
3234 test_globalinterfacetable();
3235 test_manualresetevent();
3237 /* must be last test as channel hooks can't be unregistered */
3238 test_channel_hook();
3240 CoUninitialize();