2 * Component Object Tests
4 * Copyright 2005 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
30 #include "urlmon.h" /* for CLSID_FileProtocol */
32 #include "wine/test.h"
34 /* functions that are not present on all versions of Windows */
35 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
37 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
38 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
39 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
41 static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
42 static const CLSID CLSID_CDeviceMoniker = { 0x4315d437, 0x5b8c, 0x11d0, { 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86 } };
43 static WCHAR devicedotone[] = {'d','e','v','i','c','e','.','1',0};
44 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
45 static WCHAR wszCLSID_CDeviceMoniker[] =
48 '4','3','1','5','d','4','3','7','-',
52 '0','0','a','0','c','9','1','1','c','e','8','6',
56 static const IID IID_IWineTest =
61 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
62 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
63 static const CLSID CLSID_WineOOPTest = {
67 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
68 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
72 static void LockModule(void)
74 InterlockedIncrement(&cLocks);
77 static void UnlockModule(void)
79 InterlockedDecrement(&cLocks);
82 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
87 if (ppvObj == NULL) return E_POINTER;
89 if (IsEqualGUID(riid, &IID_IUnknown) ||
90 IsEqualGUID(riid, &IID_IClassFactory))
92 *ppvObj = (LPVOID)iface;
93 IClassFactory_AddRef(iface);
101 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
104 return 2; /* non-heap-based object */
107 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
110 return 1; /* non-heap-based object */
113 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
114 LPCLASSFACTORY iface,
120 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
121 return E_NOINTERFACE;
124 static HRESULT WINAPI Test_IClassFactory_LockServer(
125 LPCLASSFACTORY iface,
131 static const IClassFactoryVtbl TestClassFactory_Vtbl =
133 Test_IClassFactory_QueryInterface,
134 Test_IClassFactory_AddRef,
135 Test_IClassFactory_Release,
136 Test_IClassFactory_CreateInstance,
137 Test_IClassFactory_LockServer
140 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
142 static void test_ProgIDFromCLSID(void)
145 HRESULT hr = ProgIDFromCLSID(&CLSID_CDeviceMoniker, &progid);
146 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
149 ok(!lstrcmpiW(progid, devicedotone), "Didn't get expected prog ID\n");
150 CoTaskMemFree(progid);
153 progid = (LPWSTR)0xdeadbeef;
154 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
155 ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
156 ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
158 hr = ProgIDFromCLSID(&CLSID_CDeviceMoniker, NULL);
159 ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
162 static void test_CLSIDFromProgID(void)
165 HRESULT hr = CLSIDFromProgID(devicedotone, &clsid);
166 ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
167 ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
169 hr = CLSIDFromString(devicedotone, &clsid);
170 ok_ole_success(hr, "CLSIDFromString");
171 ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
173 /* test some failure cases */
175 hr = CLSIDFromProgID(wszNonExistent, NULL);
176 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
178 hr = CLSIDFromProgID(NULL, &clsid);
179 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
181 memset(&clsid, 0xcc, sizeof(clsid));
182 hr = CLSIDFromProgID(wszNonExistent, &clsid);
183 ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
184 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
187 static void test_CLSIDFromString(void)
190 HRESULT hr = CLSIDFromString(wszCLSID_CDeviceMoniker, &clsid);
191 ok_ole_success(hr, "CLSIDFromString");
192 ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
194 hr = CLSIDFromString(NULL, &clsid);
195 ok_ole_success(hr, "CLSIDFromString");
196 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
199 static void test_CoCreateInstance(void)
201 REFCLSID rclsid = &CLSID_MyComputer;
202 IUnknown *pUnk = (IUnknown *)0xdeadbeef;
203 HRESULT hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
204 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
205 ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
208 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
209 ok_ole_success(hr, "CoCreateInstance");
210 IUnknown_Release(pUnk);
213 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
214 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
217 static void test_CoGetClassObject(void)
219 IUnknown *pUnk = (IUnknown *)0xdeadbeef;
220 HRESULT hr = CoGetClassObject(&CLSID_MyComputer, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
221 ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
222 ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
224 hr = CoGetClassObject(&CLSID_MyComputer, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
225 ok(hr == E_INVALIDARG, "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
228 static ATOM register_dummy_class(void)
236 GetModuleHandle(NULL),
238 LoadCursor(NULL, IDC_ARROW),
239 (HBRUSH)(COLOR_BTNFACE+1),
241 TEXT("WineOleTestClass"),
244 return RegisterClass(&wc);
247 static void test_ole_menu(void)
252 hwndFrame = CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
253 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
254 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
256 DestroyWindow(hwndFrame);
260 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
262 if (ppvObj == NULL) return E_POINTER;
264 if (IsEqualGUID(riid, &IID_IUnknown) ||
265 IsEqualGUID(riid, &IID_IClassFactory))
267 *ppvObj = (LPVOID)iface;
268 IMessageFilter_AddRef(iface);
272 return E_NOINTERFACE;
275 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
277 return 2; /* non-heap object */
280 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
282 return 1; /* non-heap object */
285 static DWORD WINAPI MessageFilter_HandleInComingCall(
286 IMessageFilter *iface,
288 HTASK threadIDCaller,
290 LPINTERFACEINFO lpInterfaceInfo)
292 trace("HandleInComingCall\n");
293 return SERVERCALL_ISHANDLED;
296 static DWORD WINAPI MessageFilter_RetryRejectedCall(
297 IMessageFilter *iface,
298 HTASK threadIDCallee,
302 trace("RetryRejectedCall\n");
306 static DWORD WINAPI MessageFilter_MessagePending(
307 IMessageFilter *iface,
308 HTASK threadIDCallee,
312 trace("MessagePending\n");
313 return PENDINGMSG_WAITNOPROCESS;
316 static const IMessageFilterVtbl MessageFilter_Vtbl =
318 MessageFilter_QueryInterface,
319 MessageFilter_AddRef,
320 MessageFilter_Release,
321 MessageFilter_HandleInComingCall,
322 MessageFilter_RetryRejectedCall,
323 MessageFilter_MessagePending
326 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
328 static void test_CoRegisterMessageFilter(void)
331 IMessageFilter *prev_filter;
333 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
334 ok(hr == CO_E_NOT_SUPPORTED,
335 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
338 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
339 prev_filter = (IMessageFilter *)0xdeadbeef;
340 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
341 ok(hr == CO_E_NOT_SUPPORTED,
342 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
344 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
345 "prev_filter should have been set to %p\n", prev_filter);
348 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
350 hr = CoRegisterMessageFilter(NULL, NULL);
351 ok_ole_success(hr, "CoRegisterMessageFilter");
353 prev_filter = (IMessageFilter *)0xdeadbeef;
354 hr = CoRegisterMessageFilter(NULL, &prev_filter);
355 ok_ole_success(hr, "CoRegisterMessageFilter");
356 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
358 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
359 ok_ole_success(hr, "CoRegisterMessageFilter");
360 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
362 hr = CoRegisterMessageFilter(NULL, NULL);
363 ok_ole_success(hr, "CoRegisterMessageFilter");
368 static HRESULT WINAPI Test_IUnknown_QueryInterface(
373 if (ppvObj == NULL) return E_POINTER;
375 if (IsEqualIID(riid, &IID_IUnknown) ||
376 IsEqualIID(riid, &IID_IWineTest))
378 *ppvObj = (LPVOID)iface;
379 IUnknown_AddRef(iface);
384 return E_NOINTERFACE;
387 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
389 return 2; /* non-heap-based object */
392 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
394 return 1; /* non-heap-based object */
397 static const IUnknownVtbl TestUnknown_Vtbl =
399 Test_IUnknown_QueryInterface,
400 Test_IUnknown_AddRef,
401 Test_IUnknown_Release,
404 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
406 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
407 IPSFactoryBuffer * This,
408 /* [in] */ REFIID riid,
409 /* [iid_is][out] */ void **ppvObject)
411 if (IsEqualIID(riid, &IID_IUnknown) ||
412 IsEqualIID(riid, &IID_IPSFactoryBuffer))
415 IPSFactoryBuffer_AddRef(This);
418 return E_NOINTERFACE;
421 static ULONG WINAPI PSFactoryBuffer_AddRef(
422 IPSFactoryBuffer * This)
427 static ULONG WINAPI PSFactoryBuffer_Release(
428 IPSFactoryBuffer * This)
433 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
434 IPSFactoryBuffer * This,
435 /* [in] */ IUnknown *pUnkOuter,
436 /* [in] */ REFIID riid,
437 /* [out] */ IRpcProxyBuffer **ppProxy,
438 /* [out] */ void **ppv)
443 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
444 IPSFactoryBuffer * This,
445 /* [in] */ REFIID riid,
446 /* [unique][in] */ IUnknown *pUnkServer,
447 /* [out] */ IRpcStubBuffer **ppStub)
452 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
454 PSFactoryBuffer_QueryInterface,
455 PSFactoryBuffer_AddRef,
456 PSFactoryBuffer_Release,
457 PSFactoryBuffer_CreateProxy,
458 PSFactoryBuffer_CreateStub
461 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
463 static const CLSID CLSID_WineTestPSFactoryBuffer =
468 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
469 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
471 static void test_CoRegisterPSClsid(void)
474 DWORD dwRegistrationKey;
478 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
479 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returened CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
481 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
483 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
484 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
485 ok_ole_success(hr, "CoRegisterClassObject");
487 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
488 ok_ole_success(hr, "CoRegisterPSClsid");
490 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
491 ok_ole_success(hr, "CreateStreamOnHGlobal");
493 hr = CoMarshalInterface(stream, &IID_IWineTest, (IUnknown *)&Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
494 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
495 IStream_Release(stream);
497 hr = CoRevokeClassObject(dwRegistrationKey);
498 ok_ole_success(hr, "CoRevokeClassObject");
502 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
504 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
505 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
510 static void test_CoGetPSClsid(void)
515 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
516 ok(hr == CO_E_NOTINITIALIZED,
517 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
520 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
522 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
523 ok_ole_success(hr, "CoGetPSClsid");
525 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
526 ok(hr == REGDB_E_IIDNOTREG,
527 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
530 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
531 ok(hr == E_INVALIDARG,
532 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
538 /* basic test, mainly for invalid arguments. see marshal.c for more */
539 static void test_CoUnmarshalInterface(void)
545 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
546 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
548 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
549 ok_ole_success(hr, "CreateStreamOnHGlobal");
551 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
553 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
555 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
557 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
558 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
562 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
563 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
565 IStream_Release(pStream);
568 static void test_CoGetInterfaceAndReleaseStream(void)
573 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
575 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
576 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
581 /* basic test, mainly for invalid arguments. see marshal.c for more */
582 static void test_CoMarshalInterface(void)
586 static const LARGE_INTEGER llZero;
588 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
590 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
591 ok_ole_success(hr, "CreateStreamOnHGlobal");
593 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
594 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
596 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
597 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
599 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
600 ok_ole_success(hr, "CoMarshalInterface");
602 /* stream not rewound */
603 hr = CoReleaseMarshalData(pStream);
604 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
606 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
607 ok_ole_success(hr, "IStream_Seek");
609 hr = CoReleaseMarshalData(pStream);
610 ok_ole_success(hr, "CoReleaseMarshalData");
612 IStream_Release(pStream);
617 static void test_CoMarshalInterThreadInterfaceInStream(void)
621 IClassFactory *pProxy;
623 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
627 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
628 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
630 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
631 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
635 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
636 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
638 ok_more_than_one_lock();
640 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
641 ok_ole_success(hr, "CoUnmarshalInterface");
643 IClassFactory_Release(pProxy);
650 static void test_CoRegisterClassObject(void)
656 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
658 /* CLSCTX_INPROC_SERVER */
659 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
660 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
661 ok_ole_success(hr, "CoRegisterClassObject");
662 hr = CoRevokeClassObject(cookie);
663 ok_ole_success(hr, "CoRevokeClassObject");
665 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
666 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
667 ok_ole_success(hr, "CoRegisterClassObject");
668 hr = CoRevokeClassObject(cookie);
669 ok_ole_success(hr, "CoRevokeClassObject");
671 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
672 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
673 ok_ole_success(hr, "CoRegisterClassObject");
674 hr = CoRevokeClassObject(cookie);
675 ok_ole_success(hr, "CoRevokeClassObject");
677 /* CLSCTX_LOCAL_SERVER */
678 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
679 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
680 ok_ole_success(hr, "CoRegisterClassObject");
681 hr = CoRevokeClassObject(cookie);
682 ok_ole_success(hr, "CoRevokeClassObject");
684 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
685 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
686 ok_ole_success(hr, "CoRegisterClassObject");
687 hr = CoRevokeClassObject(cookie);
688 ok_ole_success(hr, "CoRevokeClassObject");
690 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
691 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
692 ok_ole_success(hr, "CoRegisterClassObject");
693 hr = CoRevokeClassObject(cookie);
694 ok_ole_success(hr, "CoRevokeClassObject");
696 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
697 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
698 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
699 ok_ole_success(hr, "CoRegisterClassObject");
700 hr = CoRevokeClassObject(cookie);
701 ok_ole_success(hr, "CoRevokeClassObject");
703 /* test whether registered class becomes invalid when apartment is destroyed */
704 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
705 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
706 ok_ole_success(hr, "CoRegisterClassObject");
709 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
711 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
712 &IID_IClassFactory, (void **)&pcf);
713 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
715 /* crashes with at least win9x DCOM! */
717 hr = CoRevokeClassObject(cookie);
722 static HRESULT get_class_object(CLSCTX clsctx)
727 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
731 IClassFactory_Release(pcf);
736 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
738 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
741 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
743 hr = get_class_object(clsctx);
750 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
752 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
757 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
759 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
764 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
766 IMultiQI_Release(pMQI);
767 IClassFactory_Release(pcf);
775 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
780 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
782 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
783 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
790 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
792 DWORD cookie = (DWORD_PTR)pv;
795 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
797 hr = CoRevokeClassObject(cookie);
804 static void test_registered_object_thread_affinity(void)
812 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
814 /* CLSCTX_INPROC_SERVER */
816 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
817 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
818 ok_ole_success(hr, "CoRegisterClassObject");
820 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
821 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
822 WaitForSingleObject(thread, INFINITE);
823 GetExitCodeThread(thread, &exitcode);
825 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
826 "registered in different thread should return REGDB_E_CLASSNOTREG "
827 "instead of 0x%08x\n", hr);
829 hr = get_class_object(CLSCTX_INPROC_SERVER);
830 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
831 "thread should return S_OK instead of 0x%08x\n", hr);
833 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
834 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
835 WaitForSingleObject(thread, INFINITE);
836 GetExitCodeThread(thread, &exitcode);
838 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
840 hr = CoRevokeClassObject(cookie);
841 ok_ole_success(hr, "CoRevokeClassObject");
843 /* CLSCTX_LOCAL_SERVER */
845 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
846 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
847 ok_ole_success(hr, "CoRegisterClassObject");
849 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
850 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
851 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
854 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
856 TranslateMessage(&msg);
857 DispatchMessageA(&msg);
860 GetExitCodeThread(thread, &exitcode);
862 ok(hr == S_OK, "CoGetClassObject on local server object "
863 "registered in different thread should return S_OK "
864 "instead of 0x%08x\n", hr);
866 hr = get_class_object(CLSCTX_LOCAL_SERVER);
867 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
868 "thread should return S_OK instead of 0x%08x\n", hr);
870 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)cookie, 0, &tid);
871 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
872 WaitForSingleObject(thread, INFINITE);
873 GetExitCodeThread(thread, &exitcode);
875 ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different "
876 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
878 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
879 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
880 WaitForSingleObject(thread, INFINITE);
881 GetExitCodeThread(thread, &exitcode);
883 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
884 "thread should return S_OK instead of 0x%08x\n", hr);
886 hr = CoRevokeClassObject(cookie);
887 ok_ole_success(hr, "CoRevokeClassObject");
892 static DWORD CALLBACK free_libraries_thread(LPVOID p)
894 CoFreeUnusedLibraries();
898 static inline BOOL is_module_loaded(const char *module)
900 return GetModuleHandle(module) ? TRUE : FALSE;
903 static void test_CoFreeUnusedLibraries(void)
910 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
912 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
914 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
915 if (hr == REGDB_E_CLASSNOTREG)
917 trace("IE not installed so can't run CoFreeUnusedLibraries test\n");
920 ok_ole_success(hr, "CoCreateInstance");
922 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
924 IUnknown_Release(pUnk);
926 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
928 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
929 WaitForSingleObject(thread, INFINITE);
932 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
934 CoFreeUnusedLibraries();
936 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
944 HMODULE hOle32 = GetModuleHandle("ole32");
945 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
947 trace("You need DCOM95 installed to run this test\n");
951 test_ProgIDFromCLSID();
952 test_CLSIDFromProgID();
953 test_CLSIDFromString();
954 test_CoCreateInstance();
956 test_CoGetClassObject();
957 test_CoRegisterMessageFilter();
958 test_CoRegisterPSClsid();
960 test_CoUnmarshalInterface();
961 test_CoGetInterfaceAndReleaseStream();
962 test_CoMarshalInterface();
963 test_CoMarshalInterThreadInterfaceInStream();
964 test_CoRegisterClassObject();
965 test_registered_object_thread_affinity();
966 test_CoFreeUnusedLibraries();