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
28 #define USE_COM_CONTEXT_DEF
32 #include "urlmon.h" /* for CLSID_FileProtocol */
36 #include "wine/test.h"
38 /* functions that are not present on all versions of Windows */
39 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
40 static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
41 static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
42 static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
43 static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
44 static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
46 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
47 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
48 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
50 static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
51 static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
52 static WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
53 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
54 static WCHAR wszCLSID_StdFont[] =
56 '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
57 '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
60 static const IID IID_IWineTest =
65 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
66 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
67 static const CLSID CLSID_WineOOPTest = {
71 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
72 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
76 static void LockModule(void)
78 InterlockedIncrement(&cLocks);
81 static void UnlockModule(void)
83 InterlockedDecrement(&cLocks);
86 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
91 if (ppvObj == NULL) return E_POINTER;
93 if (IsEqualGUID(riid, &IID_IUnknown) ||
94 IsEqualGUID(riid, &IID_IClassFactory))
97 IClassFactory_AddRef(iface);
102 return E_NOINTERFACE;
105 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
108 return 2; /* non-heap-based object */
111 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
114 return 1; /* non-heap-based object */
117 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
118 LPCLASSFACTORY iface,
124 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
125 return E_NOINTERFACE;
128 static HRESULT WINAPI Test_IClassFactory_LockServer(
129 LPCLASSFACTORY iface,
135 static const IClassFactoryVtbl TestClassFactory_Vtbl =
137 Test_IClassFactory_QueryInterface,
138 Test_IClassFactory_AddRef,
139 Test_IClassFactory_Release,
140 Test_IClassFactory_CreateInstance,
141 Test_IClassFactory_LockServer
144 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
146 static void test_ProgIDFromCLSID(void)
149 HRESULT hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
150 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
153 ok(!lstrcmpiW(progid, stdfont), "Didn't get expected prog ID\n");
154 CoTaskMemFree(progid);
157 progid = (LPWSTR)0xdeadbeef;
158 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
159 ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
160 ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
162 hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
163 ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
166 static void test_CLSIDFromProgID(void)
169 HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
170 ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
171 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
173 hr = CLSIDFromString(stdfont, &clsid);
174 ok_ole_success(hr, "CLSIDFromString");
175 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
177 /* test some failure cases */
179 hr = CLSIDFromProgID(wszNonExistent, NULL);
180 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
182 hr = CLSIDFromProgID(NULL, &clsid);
183 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
185 memset(&clsid, 0xcc, sizeof(clsid));
186 hr = CLSIDFromProgID(wszNonExistent, &clsid);
187 ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
188 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
191 static void test_CLSIDFromString(void)
194 WCHAR wszCLSID_Broken[50];
197 HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
198 ok_ole_success(hr, "CLSIDFromString");
199 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
201 hr = CLSIDFromString(NULL, &clsid);
202 ok_ole_success(hr, "CLSIDFromString");
203 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
205 lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
206 for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
207 wszCLSID_Broken[i] = 'A';
208 wszCLSID_Broken[i] = '\0';
210 memset(&clsid, 0, sizeof(CLSID));
211 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
212 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
213 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
215 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
216 memset(&clsid, 0, sizeof(CLSID));
217 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
218 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
219 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
221 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
222 memset(&clsid, 0, sizeof(CLSID));
223 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
224 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
225 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
227 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
228 memset(&clsid, 0, sizeof(CLSID));
229 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
230 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
231 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
233 memset(&clsid, 0xcc, sizeof(CLSID));
234 hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
235 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
236 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
238 wszCLSID_Broken[9] = '*';
239 memset(&clsid, 0xcc, sizeof(CLSID));
240 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
241 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
242 ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
243 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
245 wszCLSID_Broken[3] = '*';
246 memset(&clsid, 0xcc, sizeof(CLSID));
247 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
248 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
249 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
250 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
252 wszCLSID_Broken[3] = '\0';
253 memset(&clsid, 0xcc, sizeof(CLSID));
254 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
255 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
256 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
257 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
260 static void test_StringFromGUID2(void)
265 /* invalid pointer */
266 SetLastError(0xdeadbeef);
267 len = StringFromGUID2(NULL,str,50);
268 ok(len == 0, "len: %d (expected 0)\n", len);
269 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
271 /* Test corner cases for buffer size */
272 len = StringFromGUID2(&CLSID_StdFont,str,50);
273 ok(len == 39, "len: %d (expected 39)\n", len);
274 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
276 memset(str,0,sizeof str);
277 len = StringFromGUID2(&CLSID_StdFont,str,39);
278 ok(len == 39, "len: %d (expected 39)\n", len);
279 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
281 len = StringFromGUID2(&CLSID_StdFont,str,38);
282 ok(len == 0, "len: %d (expected 0)\n", len);
284 len = StringFromGUID2(&CLSID_StdFont,str,30);
285 ok(len == 0, "len: %d (expected 0)\n", len);
293 static DWORD CALLBACK ole_initialize_thread(LPVOID pv)
296 struct info *info = pv;
298 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
300 SetEvent(info->wait);
301 WaitForSingleObject(info->stop, 10000);
307 static void test_CoCreateInstance(void)
314 REFCLSID rclsid = &CLSID_InternetZoneManager;
316 pUnk = (IUnknown *)0xdeadbeef;
317 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
318 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
319 ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
323 /* test errors returned for non-registered clsids */
324 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
325 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
326 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pUnk);
327 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
328 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (void **)&pUnk);
329 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
330 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_REMOTE_SERVER, &IID_IUnknown, (void **)&pUnk);
331 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
333 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
334 if(hr == REGDB_E_CLASSNOTREG)
336 skip("IE not installed so can't test CoCreateInstance\n");
341 ok_ole_success(hr, "CoCreateInstance");
342 if(pUnk) IUnknown_Release(pUnk);
345 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
346 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
348 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
349 thread has already done so */
351 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
352 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
354 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
355 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
357 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
358 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
360 ok( !WaitForSingleObject(info.wait, 10000 ), "wait timed out\n" );
362 pUnk = (IUnknown *)0xdeadbeef;
363 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
364 ok(hr == S_OK, "CoCreateInstance should have returned S_OK instead of 0x%08x\n", hr);
365 if (pUnk) IUnknown_Release(pUnk);
368 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
370 GetExitCodeThread(thread, &exitcode);
372 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
375 CloseHandle(info.wait);
376 CloseHandle(info.stop);
379 static void test_CoGetClassObject(void)
386 REFCLSID rclsid = &CLSID_InternetZoneManager;
390 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
391 ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
392 ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
394 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
395 ok(hr == E_INVALIDARG ||
396 broken(hr == CO_E_NOTINITIALIZED), /* win9x */
397 "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
399 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
400 thread has already done so */
402 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
403 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
405 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
406 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
408 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
409 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
411 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
413 pUnk = (IUnknown *)0xdeadbeef;
414 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
415 if(hr == REGDB_E_CLASSNOTREG)
416 skip("IE not installed so can't test CoGetClassObject\n");
419 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
420 if (pUnk) IUnknown_Release(pUnk);
424 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
426 GetExitCodeThread(thread, &exitcode);
428 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
431 CloseHandle(info.wait);
432 CloseHandle(info.stop);
434 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
436 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
439 IUnknown_Release(pUnk);
441 res = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &hkey);
442 ok(!res, "RegOpenKeyExA returned %d\n", res);
444 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
445 ok(!res, "RegOverridePredefKey returned %d\n", res);
447 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
448 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
450 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
451 ok(!res, "RegOverridePredefKey returned %d\n", res);
453 if (hr == S_OK) IUnknown_Release(pUnk);
459 static ATOM register_dummy_class(void)
467 GetModuleHandle(NULL),
469 LoadCursor(NULL, IDC_ARROW),
470 (HBRUSH)(COLOR_BTNFACE+1),
472 TEXT("WineOleTestClass"),
475 return RegisterClass(&wc);
478 static void test_ole_menu(void)
483 hwndFrame = CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
484 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
485 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
487 DestroyWindow(hwndFrame);
491 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
493 if (ppvObj == NULL) return E_POINTER;
495 if (IsEqualGUID(riid, &IID_IUnknown) ||
496 IsEqualGUID(riid, &IID_IClassFactory))
499 IMessageFilter_AddRef(iface);
503 return E_NOINTERFACE;
506 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
508 return 2; /* non-heap object */
511 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
513 return 1; /* non-heap object */
516 static DWORD WINAPI MessageFilter_HandleInComingCall(
517 IMessageFilter *iface,
519 HTASK threadIDCaller,
521 LPINTERFACEINFO lpInterfaceInfo)
523 trace("HandleInComingCall\n");
524 return SERVERCALL_ISHANDLED;
527 static DWORD WINAPI MessageFilter_RetryRejectedCall(
528 IMessageFilter *iface,
529 HTASK threadIDCallee,
533 trace("RetryRejectedCall\n");
537 static DWORD WINAPI MessageFilter_MessagePending(
538 IMessageFilter *iface,
539 HTASK threadIDCallee,
543 trace("MessagePending\n");
544 return PENDINGMSG_WAITNOPROCESS;
547 static const IMessageFilterVtbl MessageFilter_Vtbl =
549 MessageFilter_QueryInterface,
550 MessageFilter_AddRef,
551 MessageFilter_Release,
552 MessageFilter_HandleInComingCall,
553 MessageFilter_RetryRejectedCall,
554 MessageFilter_MessagePending
557 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
559 static void test_CoRegisterMessageFilter(void)
562 IMessageFilter *prev_filter;
564 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
565 ok(hr == CO_E_NOT_SUPPORTED,
566 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
569 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
570 prev_filter = (IMessageFilter *)0xdeadbeef;
571 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
572 ok(hr == CO_E_NOT_SUPPORTED,
573 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
575 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
576 "prev_filter should have been set to %p\n", prev_filter);
579 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
581 hr = CoRegisterMessageFilter(NULL, NULL);
582 ok_ole_success(hr, "CoRegisterMessageFilter");
584 prev_filter = (IMessageFilter *)0xdeadbeef;
585 hr = CoRegisterMessageFilter(NULL, &prev_filter);
586 ok_ole_success(hr, "CoRegisterMessageFilter");
587 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
589 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
590 ok_ole_success(hr, "CoRegisterMessageFilter");
591 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
593 hr = CoRegisterMessageFilter(NULL, NULL);
594 ok_ole_success(hr, "CoRegisterMessageFilter");
599 static HRESULT WINAPI Test_IUnknown_QueryInterface(
604 if (ppvObj == NULL) return E_POINTER;
606 if (IsEqualIID(riid, &IID_IUnknown) ||
607 IsEqualIID(riid, &IID_IWineTest))
610 IUnknown_AddRef(iface);
615 return E_NOINTERFACE;
618 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
620 return 2; /* non-heap-based object */
623 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
625 return 1; /* non-heap-based object */
628 static const IUnknownVtbl TestUnknown_Vtbl =
630 Test_IUnknown_QueryInterface,
631 Test_IUnknown_AddRef,
632 Test_IUnknown_Release,
635 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
637 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
638 IPSFactoryBuffer * This,
639 /* [in] */ REFIID riid,
640 /* [iid_is][out] */ void **ppvObject)
642 if (IsEqualIID(riid, &IID_IUnknown) ||
643 IsEqualIID(riid, &IID_IPSFactoryBuffer))
646 IPSFactoryBuffer_AddRef(This);
649 return E_NOINTERFACE;
652 static ULONG WINAPI PSFactoryBuffer_AddRef(
653 IPSFactoryBuffer * This)
658 static ULONG WINAPI PSFactoryBuffer_Release(
659 IPSFactoryBuffer * This)
664 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
665 IPSFactoryBuffer * This,
666 /* [in] */ IUnknown *pUnkOuter,
667 /* [in] */ REFIID riid,
668 /* [out] */ IRpcProxyBuffer **ppProxy,
669 /* [out] */ void **ppv)
674 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
675 IPSFactoryBuffer * This,
676 /* [in] */ REFIID riid,
677 /* [unique][in] */ IUnknown *pUnkServer,
678 /* [out] */ IRpcStubBuffer **ppStub)
683 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
685 PSFactoryBuffer_QueryInterface,
686 PSFactoryBuffer_AddRef,
687 PSFactoryBuffer_Release,
688 PSFactoryBuffer_CreateProxy,
689 PSFactoryBuffer_CreateStub
692 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
694 static const CLSID CLSID_WineTestPSFactoryBuffer =
699 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
700 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
702 static void test_CoRegisterPSClsid(void)
705 DWORD dwRegistrationKey;
709 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
710 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
712 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
714 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
715 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
716 ok_ole_success(hr, "CoRegisterClassObject");
718 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
719 ok_ole_success(hr, "CoRegisterPSClsid");
721 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
722 ok_ole_success(hr, "CreateStreamOnHGlobal");
724 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
725 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
726 IStream_Release(stream);
728 hr = CoRevokeClassObject(dwRegistrationKey);
729 ok_ole_success(hr, "CoRevokeClassObject");
733 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
735 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
736 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
741 static void test_CoGetPSClsid(void)
748 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
749 ok(hr == CO_E_NOTINITIALIZED,
750 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
753 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
755 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
756 ok_ole_success(hr, "CoGetPSClsid");
758 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
759 ok(hr == REGDB_E_IIDNOTREG,
760 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
763 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
764 ok(hr == E_INVALIDARG,
765 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
768 if (!pRegOverridePredefKey)
770 win_skip("RegOverridePredefKey not available\n");
774 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
775 ok_ole_success(hr, "CoGetPSClsid");
777 res = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &hkey);
778 ok(!res, "RegOpenKeyExA returned %d\n", res);
780 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
781 ok(!res, "RegOverridePredefKey returned %d\n", res);
783 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
784 ok_ole_success(hr, "CoGetPSClsid");
786 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
787 ok(!res, "RegOverridePredefKey returned %d\n", res);
793 /* basic test, mainly for invalid arguments. see marshal.c for more */
794 static void test_CoUnmarshalInterface(void)
800 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
801 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
803 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
804 ok_ole_success(hr, "CreateStreamOnHGlobal");
806 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
808 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
810 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
812 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
813 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
817 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
818 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
820 IStream_Release(pStream);
823 static void test_CoGetInterfaceAndReleaseStream(void)
828 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
830 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
831 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
836 /* basic test, mainly for invalid arguments. see marshal.c for more */
837 static void test_CoMarshalInterface(void)
841 static const LARGE_INTEGER llZero;
843 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
845 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
846 ok_ole_success(hr, "CreateStreamOnHGlobal");
848 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
849 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
851 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
852 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
854 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
855 ok_ole_success(hr, "CoMarshalInterface");
857 /* stream not rewound */
858 hr = CoReleaseMarshalData(pStream);
859 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
861 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
862 ok_ole_success(hr, "IStream_Seek");
864 hr = CoReleaseMarshalData(pStream);
865 ok_ole_success(hr, "CoReleaseMarshalData");
867 IStream_Release(pStream);
872 static void test_CoMarshalInterThreadInterfaceInStream(void)
876 IClassFactory *pProxy;
878 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
882 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
883 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
885 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
886 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
890 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
891 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
893 ok_more_than_one_lock();
895 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
896 ok_ole_success(hr, "CoUnmarshalInterface");
898 IClassFactory_Release(pProxy);
899 IStream_Release(pStream);
906 static void test_CoRegisterClassObject(void)
912 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
914 /* CLSCTX_INPROC_SERVER */
915 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
916 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
917 ok_ole_success(hr, "CoRegisterClassObject");
918 hr = CoRevokeClassObject(cookie);
919 ok_ole_success(hr, "CoRevokeClassObject");
921 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
922 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
923 ok_ole_success(hr, "CoRegisterClassObject");
924 hr = CoRevokeClassObject(cookie);
925 ok_ole_success(hr, "CoRevokeClassObject");
927 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
928 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
929 ok_ole_success(hr, "CoRegisterClassObject");
930 hr = CoRevokeClassObject(cookie);
931 ok_ole_success(hr, "CoRevokeClassObject");
933 /* CLSCTX_LOCAL_SERVER */
934 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
935 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
936 ok_ole_success(hr, "CoRegisterClassObject");
937 hr = CoRevokeClassObject(cookie);
938 ok_ole_success(hr, "CoRevokeClassObject");
940 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
941 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
942 ok_ole_success(hr, "CoRegisterClassObject");
943 hr = CoRevokeClassObject(cookie);
944 ok_ole_success(hr, "CoRevokeClassObject");
946 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
947 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
948 ok_ole_success(hr, "CoRegisterClassObject");
949 hr = CoRevokeClassObject(cookie);
950 ok_ole_success(hr, "CoRevokeClassObject");
952 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
953 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
954 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
955 ok_ole_success(hr, "CoRegisterClassObject");
956 hr = CoRevokeClassObject(cookie);
957 ok_ole_success(hr, "CoRevokeClassObject");
959 /* test whether an object that doesn't support IClassFactory can be
960 * registered for CLSCTX_LOCAL_SERVER */
961 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
962 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
963 ok_ole_success(hr, "CoRegisterClassObject");
964 hr = CoRevokeClassObject(cookie);
965 ok_ole_success(hr, "CoRevokeClassObject");
967 /* test whether registered class becomes invalid when apartment is destroyed */
968 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
969 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
970 ok_ole_success(hr, "CoRegisterClassObject");
973 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
975 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
976 &IID_IClassFactory, (void **)&pcf);
977 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
979 /* crashes with at least win9x DCOM! */
981 CoRevokeClassObject(cookie);
986 static HRESULT get_class_object(CLSCTX clsctx)
991 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
995 IClassFactory_Release(pcf);
1000 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1002 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1005 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1007 hr = get_class_object(clsctx);
1014 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1016 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1021 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1023 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1028 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1030 IMultiQI_Release(pMQI);
1031 IClassFactory_Release(pcf);
1039 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1044 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1046 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1047 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1054 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1056 DWORD cookie = (DWORD_PTR)pv;
1059 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1061 hr = CoRevokeClassObject(cookie);
1068 static void test_registered_object_thread_affinity(void)
1076 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1078 /* CLSCTX_INPROC_SERVER */
1080 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1081 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1082 ok_ole_success(hr, "CoRegisterClassObject");
1084 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1085 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1086 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1087 GetExitCodeThread(thread, &exitcode);
1089 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1090 "registered in different thread should return REGDB_E_CLASSNOTREG "
1091 "instead of 0x%08x\n", hr);
1093 hr = get_class_object(CLSCTX_INPROC_SERVER);
1094 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1095 "thread should return S_OK instead of 0x%08x\n", hr);
1097 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1098 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1099 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1100 GetExitCodeThread(thread, &exitcode);
1102 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1104 hr = CoRevokeClassObject(cookie);
1105 ok_ole_success(hr, "CoRevokeClassObject");
1107 /* CLSCTX_LOCAL_SERVER */
1109 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1110 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1111 ok_ole_success(hr, "CoRegisterClassObject");
1113 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1114 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1115 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1118 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1120 TranslateMessage(&msg);
1121 DispatchMessageA(&msg);
1124 GetExitCodeThread(thread, &exitcode);
1126 ok(hr == S_OK, "CoGetClassObject on local server object "
1127 "registered in different thread should return S_OK "
1128 "instead of 0x%08x\n", hr);
1130 hr = get_class_object(CLSCTX_LOCAL_SERVER);
1131 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1132 "thread should return S_OK instead of 0x%08x\n", hr);
1134 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid);
1135 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1136 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1137 GetExitCodeThread(thread, &exitcode);
1139 ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different "
1140 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1142 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1143 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1144 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1145 GetExitCodeThread(thread, &exitcode);
1147 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1148 "thread should return S_OK instead of 0x%08x\n", hr);
1150 hr = CoRevokeClassObject(cookie);
1151 ok_ole_success(hr, "CoRevokeClassObject");
1156 static DWORD CALLBACK free_libraries_thread(LPVOID p)
1158 CoFreeUnusedLibraries();
1162 static inline BOOL is_module_loaded(const char *module)
1164 return GetModuleHandle(module) != 0;
1167 static void test_CoFreeUnusedLibraries(void)
1174 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1176 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1178 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1179 if (hr == REGDB_E_CLASSNOTREG)
1181 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1185 ok_ole_success(hr, "CoCreateInstance");
1187 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1190 broken(pUnk == NULL), /* win9x */
1191 "Expected a valid pointer\n");
1193 IUnknown_Release(pUnk);
1195 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1197 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1198 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1199 CloseHandle(thread);
1201 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1203 CoFreeUnusedLibraries();
1205 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1210 static void test_CoGetObjectContext(void)
1214 IComThreadingInfo *pComThreadingInfo;
1215 IContextCallback *pContextCallback;
1216 IObjContext *pObjContext;
1221 DWORD tid, exitcode;
1223 if (!pCoGetObjectContext)
1225 skip("CoGetObjectContext not present\n");
1229 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1230 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1231 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1233 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1234 thread has already done so */
1236 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
1237 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1239 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
1240 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1242 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1243 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1245 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1247 pComThreadingInfo = NULL;
1248 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1249 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1250 IComThreadingInfo_Release(pComThreadingInfo);
1252 SetEvent(info.stop);
1253 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1255 GetExitCodeThread(thread, &exitcode);
1257 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1259 CloseHandle(thread);
1260 CloseHandle(info.wait);
1261 CloseHandle(info.stop);
1263 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1265 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1266 ok_ole_success(hr, "CoGetObjectContext");
1268 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1269 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1270 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1272 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1273 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1274 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1276 refs = IComThreadingInfo_Release(pComThreadingInfo);
1277 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1279 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1280 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1284 refs = IContextCallback_Release(pContextCallback);
1285 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1290 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1292 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1293 ok_ole_success(hr, "CoGetObjectContext");
1295 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1296 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1297 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1299 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1300 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1301 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1303 refs = IComThreadingInfo_Release(pComThreadingInfo);
1304 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1306 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1307 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1311 refs = IContextCallback_Release(pContextCallback);
1312 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1315 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1316 ok_ole_success(hr, "CoGetObjectContext");
1318 refs = IObjContext_Release(pObjContext);
1319 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
1325 IUnknown IUnknown_iface;
1329 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
1331 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
1334 static HRESULT WINAPI Test_CallContext_QueryInterface(
1339 if (ppvObj == NULL) return E_POINTER;
1341 if (IsEqualGUID(riid, &IID_IUnknown))
1344 IUnknown_AddRef(iface);
1349 return E_NOINTERFACE;
1352 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
1354 Test_CallContext *This = impl_from_IUnknown(iface);
1355 return InterlockedIncrement(&This->refs);
1358 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
1360 Test_CallContext *This = impl_from_IUnknown(iface);
1361 ULONG refs = InterlockedDecrement(&This->refs);
1363 HeapFree(GetProcessHeap(), 0, This);
1367 static const IUnknownVtbl TestCallContext_Vtbl =
1369 Test_CallContext_QueryInterface,
1370 Test_CallContext_AddRef,
1371 Test_CallContext_Release
1374 static void test_CoGetCallContext(void)
1379 Test_CallContext *test_object;
1381 if (!pCoSwitchCallContext)
1383 skip("CoSwitchCallContext not present\n");
1389 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
1390 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
1391 test_object->refs = 1;
1393 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1394 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1396 pUnk = (IUnknown*)0xdeadbeef;
1397 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
1398 ok_ole_success(hr, "CoSwitchCallContext");
1399 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
1400 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1401 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1402 IUnknown_Release(&test_object->IUnknown_iface);
1404 pUnk = (IUnknown*)0xdeadbeef;
1405 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1406 ok_ole_success(hr, "CoGetCallContext");
1407 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1408 &test_object->IUnknown_iface, pUnk);
1409 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1410 ok(refs == 3, "Expected refcount 3, got %d\n", refs);
1411 IUnknown_Release(&test_object->IUnknown_iface);
1412 IUnknown_Release(pUnk);
1414 pUnk = (IUnknown*)0xdeadbeef;
1415 hr = pCoSwitchCallContext(NULL, &pUnk);
1416 ok_ole_success(hr, "CoSwitchCallContext");
1417 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1418 &test_object->IUnknown_iface, pUnk);
1419 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1420 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1421 IUnknown_Release(&test_object->IUnknown_iface);
1423 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1424 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1426 IUnknown_Release(&test_object->IUnknown_iface);
1431 static void test_CoGetContextToken(void)
1439 DWORD tid, exitcode;
1441 if (!pCoGetContextToken)
1443 win_skip("CoGetContextToken not present\n");
1448 hr = pCoGetContextToken(&token);
1449 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
1450 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
1452 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1453 thread has already done so */
1455 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
1456 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1458 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
1459 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1461 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1462 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1464 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1467 hr = pCoGetContextToken(&token);
1468 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1470 SetEvent(info.stop);
1471 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1473 GetExitCodeThread(thread, &exitcode);
1475 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1477 CloseHandle(thread);
1478 CloseHandle(info.wait);
1479 CloseHandle(info.stop);
1483 hr = pCoGetContextToken(NULL);
1484 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
1487 hr = pCoGetContextToken(&token);
1488 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1489 ok(token, "Expected token != 0\n");
1491 refs = IUnknown_AddRef((IUnknown *)token);
1492 todo_wine ok(refs == 1, "Expected 1, got %u\n", refs);
1494 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
1495 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1496 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1498 refs = IUnknown_AddRef((IUnknown *)ctx);
1499 todo_wine ok(refs == 3, "Expected 3, got %u\n", refs);
1501 refs = IUnknown_Release((IUnknown *)ctx);
1502 todo_wine ok(refs == 2, "Expected 2, got %u\n", refs);
1504 refs = IUnknown_Release((IUnknown *)token);
1505 ok(refs == 1, "Expected 1, got %u\n", refs);
1507 /* CoGetContextToken does not add a reference */
1509 hr = pCoGetContextToken(&token);
1510 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1511 ok(token, "Expected token != 0\n");
1512 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1514 refs = IUnknown_AddRef((IUnknown *)ctx);
1515 ok(refs == 2, "Expected 1, got %u\n", refs);
1517 refs = IUnknown_Release((IUnknown *)ctx);
1518 ok(refs == 1, "Expected 0, got %u\n", refs);
1520 refs = IUnknown_Release((IUnknown *)ctx);
1521 ok(refs == 0, "Expected 0, got %u\n", refs);
1526 static void test_CoGetTreatAsClass(void)
1530 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1532 if (!pCoGetTreatAsClass)
1534 win_skip("CoGetTreatAsClass not present\n");
1537 hr = pCoGetTreatAsClass(&deadbeef,&out);
1538 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
1539 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
1542 static void test_CoInitializeEx(void)
1546 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1547 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
1549 /* Calling OleInitialize for the first time should yield S_OK even with
1550 * apartment already initialized by previous CoInitialize(Ex) calls. */
1551 hr = OleInitialize(NULL);
1552 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
1554 /* Subsequent calls to OleInitialize should return S_FALSE */
1555 hr = OleInitialize(NULL);
1556 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
1565 HMODULE hOle32 = GetModuleHandle("ole32");
1566 HMODULE hAdvapi32 = GetModuleHandle("advapi32");
1567 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
1568 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
1569 pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
1570 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
1571 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
1572 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
1574 trace("You need DCOM95 installed to run this test\n");
1578 test_ProgIDFromCLSID();
1579 test_CLSIDFromProgID();
1580 test_CLSIDFromString();
1581 test_StringFromGUID2();
1582 test_CoCreateInstance();
1584 test_CoGetClassObject();
1585 test_CoRegisterMessageFilter();
1586 test_CoRegisterPSClsid();
1587 test_CoGetPSClsid();
1588 test_CoUnmarshalInterface();
1589 test_CoGetInterfaceAndReleaseStream();
1590 test_CoMarshalInterface();
1591 test_CoMarshalInterThreadInterfaceInStream();
1592 test_CoRegisterClassObject();
1593 test_registered_object_thread_affinity();
1594 test_CoFreeUnusedLibraries();
1595 test_CoGetObjectContext();
1596 test_CoGetCallContext();
1597 test_CoGetContextToken();
1598 test_CoGetTreatAsClass();
1599 test_CoInitializeEx();