Release 1.6-rc2.
[wine/testsucceed.git] / dlls / ole32 / tests / compobj.c
blob470adbd6d37ffd6f41aac15840dfc2755a84585f
1 /*
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
21 #define COBJMACROS
22 #define CONST_VTABLE
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #define USE_COM_CONTEXT_DEF
29 #include "initguid.h"
30 #include "objbase.h"
31 #include "shlguid.h"
32 #include "urlmon.h" /* for CLSID_FileProtocol */
34 #include "ctxtcall.h"
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 =
62 0x5201163f,
63 0x8164,
64 0x4fd0,
65 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
66 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
67 static const CLSID CLSID_WineOOPTest = {
68 0x5201163f,
69 0x8164,
70 0x4fd0,
71 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
72 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
74 static LONG cLocks;
76 static void LockModule(void)
78 InterlockedIncrement(&cLocks);
81 static void UnlockModule(void)
83 InterlockedDecrement(&cLocks);
86 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
87 LPCLASSFACTORY iface,
88 REFIID riid,
89 LPVOID *ppvObj)
91 if (ppvObj == NULL) return E_POINTER;
93 if (IsEqualGUID(riid, &IID_IUnknown) ||
94 IsEqualGUID(riid, &IID_IClassFactory))
96 *ppvObj = iface;
97 IClassFactory_AddRef(iface);
98 return S_OK;
101 *ppvObj = NULL;
102 return E_NOINTERFACE;
105 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
107 LockModule();
108 return 2; /* non-heap-based object */
111 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
113 UnlockModule();
114 return 1; /* non-heap-based object */
117 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
118 LPCLASSFACTORY iface,
119 IUnknown *pUnkOuter,
120 REFIID riid,
121 LPVOID *ppvObj)
123 *ppvObj = NULL;
124 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
125 return E_NOINTERFACE;
128 static HRESULT WINAPI Test_IClassFactory_LockServer(
129 LPCLASSFACTORY iface,
130 BOOL fLock)
132 return S_OK;
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)
148 LPWSTR progid;
149 HRESULT hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
150 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
151 if (hr == S_OK)
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)
168 CLSID clsid;
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)
193 CLSID clsid;
194 WCHAR wszCLSID_Broken[50];
195 UINT i;
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)
262 WCHAR str[50];
263 int len;
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);
288 struct info
290 HANDLE wait, stop;
293 static DWORD CALLBACK ole_initialize_thread(LPVOID pv)
295 HRESULT hr;
296 struct info *info = pv;
298 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
300 SetEvent(info->wait);
301 WaitForSingleObject(info->stop, 10000);
303 CoUninitialize();
304 return hr;
307 static void test_CoCreateInstance(void)
309 HRESULT hr;
310 HANDLE thread;
311 DWORD tid, exitcode;
312 IUnknown *pUnk;
313 struct info info;
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);
321 OleInitialize(NULL);
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");
337 OleUninitialize();
338 return;
341 ok_ole_success(hr, "CoCreateInstance");
342 if(pUnk) IUnknown_Release(pUnk);
343 OleUninitialize();
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);
367 SetEvent(info.stop);
368 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
370 GetExitCodeThread(thread, &exitcode);
371 hr = exitcode;
372 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
374 CloseHandle(thread);
375 CloseHandle(info.wait);
376 CloseHandle(info.stop);
379 static void test_CoGetClassObject(void)
381 HRESULT hr;
382 HANDLE thread;
383 DWORD tid, exitcode;
384 IUnknown *pUnk;
385 struct info info;
386 REFCLSID rclsid = &CLSID_InternetZoneManager;
387 HKEY hkey;
388 LONG res;
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");
417 else
419 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
420 if (pUnk) IUnknown_Release(pUnk);
423 SetEvent(info.stop);
424 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
426 GetExitCodeThread(thread, &exitcode);
427 hr = exitcode;
428 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
430 CloseHandle(thread);
431 CloseHandle(info.wait);
432 CloseHandle(info.stop);
434 if (!pRegOverridePredefKey)
436 win_skip("RegOverridePredefKey not available\n");
437 return;
440 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
442 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
443 if (hr == S_OK)
445 IUnknown_Release(pUnk);
447 res = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
448 KEY_ALL_ACCESS, NULL, &hkey, NULL);
449 ok(!res, "RegCreateKeyEx returned %d\n", res);
451 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
452 ok(!res, "RegOverridePredefKey returned %d\n", res);
454 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
455 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
457 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
458 ok(!res, "RegOverridePredefKey returned %d\n", res);
460 if (hr == S_OK) IUnknown_Release(pUnk);
461 RegCloseKey(hkey);
463 CoUninitialize();
466 static ATOM register_dummy_class(void)
468 WNDCLASS wc =
471 DefWindowProc,
474 GetModuleHandle(NULL),
475 NULL,
476 LoadCursor(NULL, IDC_ARROW),
477 (HBRUSH)(COLOR_BTNFACE+1),
478 NULL,
479 TEXT("WineOleTestClass"),
482 return RegisterClass(&wc);
485 static void test_ole_menu(void)
487 HWND hwndFrame;
488 HRESULT hr;
490 hwndFrame = CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
491 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
492 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
494 DestroyWindow(hwndFrame);
498 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
500 if (ppvObj == NULL) return E_POINTER;
502 if (IsEqualGUID(riid, &IID_IUnknown) ||
503 IsEqualGUID(riid, &IID_IClassFactory))
505 *ppvObj = iface;
506 IMessageFilter_AddRef(iface);
507 return S_OK;
510 return E_NOINTERFACE;
513 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
515 return 2; /* non-heap object */
518 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
520 return 1; /* non-heap object */
523 static DWORD WINAPI MessageFilter_HandleInComingCall(
524 IMessageFilter *iface,
525 DWORD dwCallType,
526 HTASK threadIDCaller,
527 DWORD dwTickCount,
528 LPINTERFACEINFO lpInterfaceInfo)
530 trace("HandleInComingCall\n");
531 return SERVERCALL_ISHANDLED;
534 static DWORD WINAPI MessageFilter_RetryRejectedCall(
535 IMessageFilter *iface,
536 HTASK threadIDCallee,
537 DWORD dwTickCount,
538 DWORD dwRejectType)
540 trace("RetryRejectedCall\n");
541 return 0;
544 static DWORD WINAPI MessageFilter_MessagePending(
545 IMessageFilter *iface,
546 HTASK threadIDCallee,
547 DWORD dwTickCount,
548 DWORD dwPendingType)
550 trace("MessagePending\n");
551 return PENDINGMSG_WAITNOPROCESS;
554 static const IMessageFilterVtbl MessageFilter_Vtbl =
556 MessageFilter_QueryInterface,
557 MessageFilter_AddRef,
558 MessageFilter_Release,
559 MessageFilter_HandleInComingCall,
560 MessageFilter_RetryRejectedCall,
561 MessageFilter_MessagePending
564 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
566 static void test_CoRegisterMessageFilter(void)
568 HRESULT hr;
569 IMessageFilter *prev_filter;
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",
574 hr);
576 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
577 prev_filter = (IMessageFilter *)0xdeadbeef;
578 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
579 ok(hr == CO_E_NOT_SUPPORTED,
580 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
581 hr);
582 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
583 "prev_filter should have been set to %p\n", prev_filter);
584 CoUninitialize();
586 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
588 hr = CoRegisterMessageFilter(NULL, NULL);
589 ok_ole_success(hr, "CoRegisterMessageFilter");
591 prev_filter = (IMessageFilter *)0xdeadbeef;
592 hr = CoRegisterMessageFilter(NULL, &prev_filter);
593 ok_ole_success(hr, "CoRegisterMessageFilter");
594 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
596 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
597 ok_ole_success(hr, "CoRegisterMessageFilter");
598 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
600 hr = CoRegisterMessageFilter(NULL, NULL);
601 ok_ole_success(hr, "CoRegisterMessageFilter");
603 CoUninitialize();
606 static HRESULT WINAPI Test_IUnknown_QueryInterface(
607 IUnknown *iface,
608 REFIID riid,
609 LPVOID *ppvObj)
611 if (ppvObj == NULL) return E_POINTER;
613 if (IsEqualIID(riid, &IID_IUnknown) ||
614 IsEqualIID(riid, &IID_IWineTest))
616 *ppvObj = iface;
617 IUnknown_AddRef(iface);
618 return S_OK;
621 *ppvObj = NULL;
622 return E_NOINTERFACE;
625 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
627 return 2; /* non-heap-based object */
630 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
632 return 1; /* non-heap-based object */
635 static const IUnknownVtbl TestUnknown_Vtbl =
637 Test_IUnknown_QueryInterface,
638 Test_IUnknown_AddRef,
639 Test_IUnknown_Release,
642 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
644 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
645 IPSFactoryBuffer * This,
646 /* [in] */ REFIID riid,
647 /* [iid_is][out] */ void **ppvObject)
649 if (IsEqualIID(riid, &IID_IUnknown) ||
650 IsEqualIID(riid, &IID_IPSFactoryBuffer))
652 *ppvObject = This;
653 IPSFactoryBuffer_AddRef(This);
654 return S_OK;
656 return E_NOINTERFACE;
659 static ULONG WINAPI PSFactoryBuffer_AddRef(
660 IPSFactoryBuffer * This)
662 return 2;
665 static ULONG WINAPI PSFactoryBuffer_Release(
666 IPSFactoryBuffer * This)
668 return 1;
671 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
672 IPSFactoryBuffer * This,
673 /* [in] */ IUnknown *pUnkOuter,
674 /* [in] */ REFIID riid,
675 /* [out] */ IRpcProxyBuffer **ppProxy,
676 /* [out] */ void **ppv)
678 return E_NOTIMPL;
681 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
682 IPSFactoryBuffer * This,
683 /* [in] */ REFIID riid,
684 /* [unique][in] */ IUnknown *pUnkServer,
685 /* [out] */ IRpcStubBuffer **ppStub)
687 return E_NOTIMPL;
690 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
692 PSFactoryBuffer_QueryInterface,
693 PSFactoryBuffer_AddRef,
694 PSFactoryBuffer_Release,
695 PSFactoryBuffer_CreateProxy,
696 PSFactoryBuffer_CreateStub
699 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
701 static const CLSID CLSID_WineTestPSFactoryBuffer =
703 0x52011640,
704 0x8164,
705 0x4fd0,
706 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
707 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
709 static void test_CoRegisterPSClsid(void)
711 HRESULT hr;
712 DWORD dwRegistrationKey;
713 IStream *stream;
714 CLSID clsid;
716 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
717 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
719 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
721 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
722 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
723 ok_ole_success(hr, "CoRegisterClassObject");
725 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
726 ok_ole_success(hr, "CoRegisterPSClsid");
728 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
729 ok_ole_success(hr, "CreateStreamOnHGlobal");
731 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
732 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
733 IStream_Release(stream);
735 hr = CoRevokeClassObject(dwRegistrationKey);
736 ok_ole_success(hr, "CoRevokeClassObject");
738 CoUninitialize();
740 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
742 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
743 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
745 CoUninitialize();
748 static void test_CoGetPSClsid(void)
750 HRESULT hr;
751 CLSID clsid;
752 HKEY hkey;
753 LONG res;
755 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
756 ok(hr == CO_E_NOTINITIALIZED,
757 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
758 hr);
760 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
762 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
763 ok_ole_success(hr, "CoGetPSClsid");
765 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
766 ok(hr == REGDB_E_IIDNOTREG,
767 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
768 hr);
770 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
771 ok(hr == E_INVALIDARG,
772 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
773 hr);
775 if (!pRegOverridePredefKey)
777 win_skip("RegOverridePredefKey not available\n");
778 CoUninitialize();
779 return;
781 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
782 ok_ole_success(hr, "CoGetPSClsid");
784 res = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
785 KEY_ALL_ACCESS, NULL, &hkey, NULL);
786 ok(!res, "RegCreateKeyEx returned %d\n", res);
788 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
789 ok(!res, "RegOverridePredefKey returned %d\n", res);
791 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
792 ok_ole_success(hr, "CoGetPSClsid");
794 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
795 ok(!res, "RegOverridePredefKey returned %d\n", res);
797 RegCloseKey(hkey);
798 CoUninitialize();
801 /* basic test, mainly for invalid arguments. see marshal.c for more */
802 static void test_CoUnmarshalInterface(void)
804 IUnknown *pProxy;
805 IStream *pStream;
806 HRESULT hr;
808 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
809 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
811 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
812 ok_ole_success(hr, "CreateStreamOnHGlobal");
814 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
815 todo_wine
816 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
818 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
820 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
821 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
823 CoUninitialize();
825 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
826 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
828 IStream_Release(pStream);
831 static void test_CoGetInterfaceAndReleaseStream(void)
833 HRESULT hr;
834 IUnknown *pUnk;
836 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
838 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
839 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
841 CoUninitialize();
844 /* basic test, mainly for invalid arguments. see marshal.c for more */
845 static void test_CoMarshalInterface(void)
847 IStream *pStream;
848 HRESULT hr;
849 static const LARGE_INTEGER llZero;
851 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
853 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
854 ok_ole_success(hr, "CreateStreamOnHGlobal");
856 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
857 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
859 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
860 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
862 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
863 ok_ole_success(hr, "CoMarshalInterface");
865 /* stream not rewound */
866 hr = CoReleaseMarshalData(pStream);
867 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
869 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
870 ok_ole_success(hr, "IStream_Seek");
872 hr = CoReleaseMarshalData(pStream);
873 ok_ole_success(hr, "CoReleaseMarshalData");
875 IStream_Release(pStream);
877 CoUninitialize();
880 static void test_CoMarshalInterThreadInterfaceInStream(void)
882 IStream *pStream;
883 HRESULT hr;
884 IClassFactory *pProxy;
886 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
888 cLocks = 0;
890 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
891 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
893 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
894 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
896 ok_no_locks();
898 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
899 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
901 ok_more_than_one_lock();
903 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
904 ok_ole_success(hr, "CoUnmarshalInterface");
906 IClassFactory_Release(pProxy);
907 IStream_Release(pStream);
909 ok_no_locks();
911 CoUninitialize();
914 static void test_CoRegisterClassObject(void)
916 DWORD cookie;
917 HRESULT hr;
918 IClassFactory *pcf;
920 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
922 /* CLSCTX_INPROC_SERVER */
923 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
924 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
925 ok_ole_success(hr, "CoRegisterClassObject");
926 hr = CoRevokeClassObject(cookie);
927 ok_ole_success(hr, "CoRevokeClassObject");
929 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
930 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
931 ok_ole_success(hr, "CoRegisterClassObject");
932 hr = CoRevokeClassObject(cookie);
933 ok_ole_success(hr, "CoRevokeClassObject");
935 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
936 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
937 ok_ole_success(hr, "CoRegisterClassObject");
938 hr = CoRevokeClassObject(cookie);
939 ok_ole_success(hr, "CoRevokeClassObject");
941 /* CLSCTX_LOCAL_SERVER */
942 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
943 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
944 ok_ole_success(hr, "CoRegisterClassObject");
945 hr = CoRevokeClassObject(cookie);
946 ok_ole_success(hr, "CoRevokeClassObject");
948 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
949 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
950 ok_ole_success(hr, "CoRegisterClassObject");
951 hr = CoRevokeClassObject(cookie);
952 ok_ole_success(hr, "CoRevokeClassObject");
954 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
955 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
956 ok_ole_success(hr, "CoRegisterClassObject");
957 hr = CoRevokeClassObject(cookie);
958 ok_ole_success(hr, "CoRevokeClassObject");
960 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
961 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
962 CLSCTX_INPROC_SERVER|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 an object that doesn't support IClassFactory can be
968 * registered for CLSCTX_LOCAL_SERVER */
969 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
970 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
971 ok_ole_success(hr, "CoRegisterClassObject");
972 hr = CoRevokeClassObject(cookie);
973 ok_ole_success(hr, "CoRevokeClassObject");
975 /* test whether registered class becomes invalid when apartment is destroyed */
976 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
977 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
978 ok_ole_success(hr, "CoRegisterClassObject");
980 CoUninitialize();
981 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
983 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
984 &IID_IClassFactory, (void **)&pcf);
985 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
987 /* crashes with at least win9x DCOM! */
988 if (0)
989 CoRevokeClassObject(cookie);
991 CoUninitialize();
994 static HRESULT get_class_object(CLSCTX clsctx)
996 HRESULT hr;
997 IClassFactory *pcf;
999 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1000 (void **)&pcf);
1002 if (SUCCEEDED(hr))
1003 IClassFactory_Release(pcf);
1005 return hr;
1008 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1010 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1011 HRESULT hr;
1013 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1015 hr = get_class_object(clsctx);
1017 CoUninitialize();
1019 return hr;
1022 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1024 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1025 HRESULT hr;
1026 IClassFactory *pcf;
1027 IMultiQI *pMQI;
1029 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1031 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1032 (void **)&pcf);
1034 if (SUCCEEDED(hr))
1036 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1037 if (SUCCEEDED(hr))
1038 IMultiQI_Release(pMQI);
1039 IClassFactory_Release(pcf);
1042 CoUninitialize();
1044 return hr;
1047 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1049 HRESULT hr;
1050 DWORD cookie;
1052 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1054 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1055 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1057 CoUninitialize();
1059 return hr;
1062 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1064 DWORD cookie = (DWORD_PTR)pv;
1065 HRESULT hr;
1067 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1069 hr = CoRevokeClassObject(cookie);
1071 CoUninitialize();
1073 return hr;
1076 static void test_registered_object_thread_affinity(void)
1078 HRESULT hr;
1079 DWORD cookie;
1080 HANDLE thread;
1081 DWORD tid;
1082 DWORD exitcode;
1084 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1086 /* CLSCTX_INPROC_SERVER */
1088 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1089 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1090 ok_ole_success(hr, "CoRegisterClassObject");
1092 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1093 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1094 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1095 GetExitCodeThread(thread, &exitcode);
1096 hr = exitcode;
1097 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1098 "registered in different thread should return REGDB_E_CLASSNOTREG "
1099 "instead of 0x%08x\n", hr);
1101 hr = get_class_object(CLSCTX_INPROC_SERVER);
1102 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1103 "thread should return S_OK instead of 0x%08x\n", hr);
1105 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1106 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1107 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1108 GetExitCodeThread(thread, &exitcode);
1109 hr = exitcode;
1110 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1112 hr = CoRevokeClassObject(cookie);
1113 ok_ole_success(hr, "CoRevokeClassObject");
1115 /* CLSCTX_LOCAL_SERVER */
1117 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1118 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1119 ok_ole_success(hr, "CoRegisterClassObject");
1121 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1122 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1123 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1125 MSG msg;
1126 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1128 TranslateMessage(&msg);
1129 DispatchMessageA(&msg);
1132 GetExitCodeThread(thread, &exitcode);
1133 hr = exitcode;
1134 ok(hr == S_OK, "CoGetClassObject on local server object "
1135 "registered in different thread should return S_OK "
1136 "instead of 0x%08x\n", hr);
1138 hr = get_class_object(CLSCTX_LOCAL_SERVER);
1139 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1140 "thread should return S_OK instead of 0x%08x\n", hr);
1142 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 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);
1146 hr = exitcode;
1147 ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different "
1148 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1150 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1151 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1152 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1153 GetExitCodeThread(thread, &exitcode);
1154 hr = exitcode;
1155 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1156 "thread should return S_OK instead of 0x%08x\n", hr);
1158 hr = CoRevokeClassObject(cookie);
1159 ok_ole_success(hr, "CoRevokeClassObject");
1161 CoUninitialize();
1164 static DWORD CALLBACK free_libraries_thread(LPVOID p)
1166 CoFreeUnusedLibraries();
1167 return 0;
1170 static inline BOOL is_module_loaded(const char *module)
1172 return GetModuleHandle(module) != 0;
1175 static void test_CoFreeUnusedLibraries(void)
1177 HRESULT hr;
1178 IUnknown *pUnk;
1179 DWORD tid;
1180 HANDLE thread;
1182 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1184 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1186 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1187 if (hr == REGDB_E_CLASSNOTREG)
1189 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1190 CoUninitialize();
1191 return;
1193 ok_ole_success(hr, "CoCreateInstance");
1195 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1197 ok(pUnk != NULL ||
1198 broken(pUnk == NULL), /* win9x */
1199 "Expected a valid pointer\n");
1200 if (pUnk)
1201 IUnknown_Release(pUnk);
1203 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1205 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1206 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1207 CloseHandle(thread);
1209 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1211 CoFreeUnusedLibraries();
1213 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1215 CoUninitialize();
1218 static void test_CoGetObjectContext(void)
1220 HRESULT hr;
1221 ULONG refs;
1222 IComThreadingInfo *pComThreadingInfo;
1223 IContextCallback *pContextCallback;
1224 IObjContext *pObjContext;
1225 APTTYPE apttype;
1226 THDTYPE thdtype;
1227 struct info info;
1228 HANDLE thread;
1229 DWORD tid, exitcode;
1231 if (!pCoGetObjectContext)
1233 skip("CoGetObjectContext not present\n");
1234 return;
1237 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1238 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1239 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1241 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1242 thread has already done so */
1244 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
1245 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1247 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
1248 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1250 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1251 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1253 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1255 pComThreadingInfo = NULL;
1256 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1257 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1258 IComThreadingInfo_Release(pComThreadingInfo);
1260 SetEvent(info.stop);
1261 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1263 GetExitCodeThread(thread, &exitcode);
1264 hr = exitcode;
1265 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1267 CloseHandle(thread);
1268 CloseHandle(info.wait);
1269 CloseHandle(info.stop);
1271 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1273 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1274 ok_ole_success(hr, "CoGetObjectContext");
1276 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1277 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1278 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1280 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1281 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1282 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1284 refs = IComThreadingInfo_Release(pComThreadingInfo);
1285 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1287 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1288 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1290 if (hr == S_OK)
1292 refs = IContextCallback_Release(pContextCallback);
1293 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1296 CoUninitialize();
1298 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1300 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1301 ok_ole_success(hr, "CoGetObjectContext");
1303 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1304 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1305 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1307 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1308 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1309 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1311 refs = IComThreadingInfo_Release(pComThreadingInfo);
1312 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1314 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1315 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1317 if (hr == S_OK)
1319 refs = IContextCallback_Release(pContextCallback);
1320 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1323 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1324 ok_ole_success(hr, "CoGetObjectContext");
1326 refs = IObjContext_Release(pObjContext);
1327 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
1329 CoUninitialize();
1332 typedef struct {
1333 IUnknown IUnknown_iface;
1334 LONG refs;
1335 } Test_CallContext;
1337 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
1339 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
1342 static HRESULT WINAPI Test_CallContext_QueryInterface(
1343 IUnknown *iface,
1344 REFIID riid,
1345 LPVOID *ppvObj)
1347 if (ppvObj == NULL) return E_POINTER;
1349 if (IsEqualGUID(riid, &IID_IUnknown))
1351 *ppvObj = iface;
1352 IUnknown_AddRef(iface);
1353 return S_OK;
1356 *ppvObj = NULL;
1357 return E_NOINTERFACE;
1360 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
1362 Test_CallContext *This = impl_from_IUnknown(iface);
1363 return InterlockedIncrement(&This->refs);
1366 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
1368 Test_CallContext *This = impl_from_IUnknown(iface);
1369 ULONG refs = InterlockedDecrement(&This->refs);
1370 if (!refs)
1371 HeapFree(GetProcessHeap(), 0, This);
1372 return refs;
1375 static const IUnknownVtbl TestCallContext_Vtbl =
1377 Test_CallContext_QueryInterface,
1378 Test_CallContext_AddRef,
1379 Test_CallContext_Release
1382 static void test_CoGetCallContext(void)
1384 HRESULT hr;
1385 ULONG refs;
1386 IUnknown *pUnk;
1387 Test_CallContext *test_object;
1389 if (!pCoSwitchCallContext)
1391 skip("CoSwitchCallContext not present\n");
1392 return;
1395 CoInitialize(NULL);
1397 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
1398 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
1399 test_object->refs = 1;
1401 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1402 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1404 pUnk = (IUnknown*)0xdeadbeef;
1405 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
1406 ok_ole_success(hr, "CoSwitchCallContext");
1407 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
1408 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1409 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1410 IUnknown_Release(&test_object->IUnknown_iface);
1412 pUnk = (IUnknown*)0xdeadbeef;
1413 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1414 ok_ole_success(hr, "CoGetCallContext");
1415 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1416 &test_object->IUnknown_iface, pUnk);
1417 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1418 ok(refs == 3, "Expected refcount 3, got %d\n", refs);
1419 IUnknown_Release(&test_object->IUnknown_iface);
1420 IUnknown_Release(pUnk);
1422 pUnk = (IUnknown*)0xdeadbeef;
1423 hr = pCoSwitchCallContext(NULL, &pUnk);
1424 ok_ole_success(hr, "CoSwitchCallContext");
1425 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1426 &test_object->IUnknown_iface, pUnk);
1427 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1428 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1429 IUnknown_Release(&test_object->IUnknown_iface);
1431 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1432 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1434 IUnknown_Release(&test_object->IUnknown_iface);
1436 CoUninitialize();
1439 static void test_CoGetContextToken(void)
1441 HRESULT hr;
1442 ULONG refs;
1443 ULONG_PTR token;
1444 IObjContext *ctx;
1445 struct info info;
1446 HANDLE thread;
1447 DWORD tid, exitcode;
1449 if (!pCoGetContextToken)
1451 win_skip("CoGetContextToken not present\n");
1452 return;
1455 token = 0xdeadbeef;
1456 hr = pCoGetContextToken(&token);
1457 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
1458 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
1460 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1461 thread has already done so */
1463 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
1464 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1466 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
1467 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1469 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1470 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1472 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1474 token = 0;
1475 hr = pCoGetContextToken(&token);
1476 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1478 SetEvent(info.stop);
1479 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1481 GetExitCodeThread(thread, &exitcode);
1482 hr = exitcode;
1483 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1485 CloseHandle(thread);
1486 CloseHandle(info.wait);
1487 CloseHandle(info.stop);
1489 CoInitialize(NULL);
1491 hr = pCoGetContextToken(NULL);
1492 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
1494 token = 0;
1495 hr = pCoGetContextToken(&token);
1496 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1497 ok(token, "Expected token != 0\n");
1499 refs = IUnknown_AddRef((IUnknown *)token);
1500 todo_wine ok(refs == 1, "Expected 1, got %u\n", refs);
1502 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
1503 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1504 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1506 refs = IUnknown_AddRef((IUnknown *)ctx);
1507 todo_wine ok(refs == 3, "Expected 3, got %u\n", refs);
1509 refs = IUnknown_Release((IUnknown *)ctx);
1510 todo_wine ok(refs == 2, "Expected 2, got %u\n", refs);
1512 refs = IUnknown_Release((IUnknown *)token);
1513 ok(refs == 1, "Expected 1, got %u\n", refs);
1515 /* CoGetContextToken does not add a reference */
1516 token = 0;
1517 hr = pCoGetContextToken(&token);
1518 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1519 ok(token, "Expected token != 0\n");
1520 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1522 refs = IUnknown_AddRef((IUnknown *)ctx);
1523 ok(refs == 2, "Expected 1, got %u\n", refs);
1525 refs = IUnknown_Release((IUnknown *)ctx);
1526 ok(refs == 1, "Expected 0, got %u\n", refs);
1528 refs = IUnknown_Release((IUnknown *)ctx);
1529 ok(refs == 0, "Expected 0, got %u\n", refs);
1531 CoUninitialize();
1534 static void test_CoGetTreatAsClass(void)
1536 HRESULT hr;
1537 CLSID out;
1538 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1540 if (!pCoGetTreatAsClass)
1542 win_skip("CoGetTreatAsClass not present\n");
1543 return;
1545 hr = pCoGetTreatAsClass(&deadbeef,&out);
1546 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
1547 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
1550 static void test_CoInitializeEx(void)
1552 HRESULT hr;
1554 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1555 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
1557 /* Calling OleInitialize for the first time should yield S_OK even with
1558 * apartment already initialized by previous CoInitialize(Ex) calls. */
1559 hr = OleInitialize(NULL);
1560 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
1562 /* Subsequent calls to OleInitialize should return S_FALSE */
1563 hr = OleInitialize(NULL);
1564 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
1566 /* Cleanup */
1567 CoUninitialize();
1568 OleUninitialize();
1571 START_TEST(compobj)
1573 HMODULE hOle32 = GetModuleHandle("ole32");
1574 HMODULE hAdvapi32 = GetModuleHandle("advapi32");
1575 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
1576 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
1577 pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
1578 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
1579 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
1580 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
1582 trace("You need DCOM95 installed to run this test\n");
1583 return;
1586 test_ProgIDFromCLSID();
1587 test_CLSIDFromProgID();
1588 test_CLSIDFromString();
1589 test_StringFromGUID2();
1590 test_CoCreateInstance();
1591 test_ole_menu();
1592 test_CoGetClassObject();
1593 test_CoRegisterMessageFilter();
1594 test_CoRegisterPSClsid();
1595 test_CoGetPSClsid();
1596 test_CoUnmarshalInterface();
1597 test_CoGetInterfaceAndReleaseStream();
1598 test_CoMarshalInterface();
1599 test_CoMarshalInterThreadInterfaceInStream();
1600 test_CoRegisterClassObject();
1601 test_registered_object_thread_affinity();
1602 test_CoFreeUnusedLibraries();
1603 test_CoGetObjectContext();
1604 test_CoGetCallContext();
1605 test_CoGetContextToken();
1606 test_CoGetTreatAsClass();
1607 test_CoInitializeEx();