ole32: Missing MiscStatus key is not a failure for OleRegGetMiscStatus().
[wine/wine-gecko.git] / dlls / ole32 / tests / compobj.c
blob519cb7435dc1d404f5e136564ced423edb26fbc6
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>
25 #include <stdio.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #define USE_COM_CONTEXT_DEF
30 #include "initguid.h"
31 #include "objbase.h"
32 #include "shlguid.h"
33 #include "urlmon.h" /* for CLSID_FileProtocol */
35 #include "ctxtcall.h"
37 #include "wine/test.h"
39 /* functions that are not present on all versions of Windows */
40 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
41 static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
42 static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
43 static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
44 static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
45 static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
47 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
48 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
49 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
50 static void (WINAPI *pReleaseActCtx)(HANDLE);
52 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
53 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
54 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
56 static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
57 static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
58 static WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
59 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
60 static WCHAR wszCLSID_StdFont[] =
62 '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
63 '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
65 static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
67 DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
68 DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
70 static const char *debugstr_guid(REFIID riid)
72 static char buf[50];
74 sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
75 riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
76 riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
77 riid->Data4[5], riid->Data4[6], riid->Data4[7]);
79 return buf;
82 static LONG cLocks;
84 static void LockModule(void)
86 InterlockedIncrement(&cLocks);
89 static void UnlockModule(void)
91 InterlockedDecrement(&cLocks);
94 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
95 LPCLASSFACTORY iface,
96 REFIID riid,
97 LPVOID *ppvObj)
99 if (ppvObj == NULL) return E_POINTER;
101 if (IsEqualGUID(riid, &IID_IUnknown) ||
102 IsEqualGUID(riid, &IID_IClassFactory))
104 *ppvObj = iface;
105 IClassFactory_AddRef(iface);
106 return S_OK;
109 *ppvObj = NULL;
110 return E_NOINTERFACE;
113 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
115 LockModule();
116 return 2; /* non-heap-based object */
119 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
121 UnlockModule();
122 return 1; /* non-heap-based object */
125 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
126 LPCLASSFACTORY iface,
127 IUnknown *pUnkOuter,
128 REFIID riid,
129 LPVOID *ppvObj)
131 *ppvObj = NULL;
132 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
133 return E_NOINTERFACE;
136 static HRESULT WINAPI Test_IClassFactory_LockServer(
137 LPCLASSFACTORY iface,
138 BOOL fLock)
140 return S_OK;
143 static const IClassFactoryVtbl TestClassFactory_Vtbl =
145 Test_IClassFactory_QueryInterface,
146 Test_IClassFactory_AddRef,
147 Test_IClassFactory_Release,
148 Test_IClassFactory_CreateInstance,
149 Test_IClassFactory_LockServer
152 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
154 static WCHAR manifest_path[MAX_PATH];
156 static BOOL create_manifest_file(const char *filename, const char *manifest)
158 int manifest_len;
159 DWORD size;
160 HANDLE file;
161 WCHAR path[MAX_PATH];
163 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
164 GetFullPathNameW(path, sizeof(manifest_path)/sizeof(WCHAR), manifest_path, NULL);
166 manifest_len = strlen(manifest);
167 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
168 FILE_ATTRIBUTE_NORMAL, NULL);
169 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
170 if(file == INVALID_HANDLE_VALUE)
171 return FALSE;
172 WriteFile(file, manifest, manifest_len, &size, NULL);
173 CloseHandle(file);
175 return TRUE;
178 static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie)
180 WCHAR path[MAX_PATH];
181 ACTCTXW actctx;
182 HANDLE handle;
183 BOOL ret;
185 if (!pCreateActCtxW) return NULL;
187 create_manifest_file("file.manifest", manifest);
189 MultiByteToWideChar( CP_ACP, 0, "file.manifest", -1, path, MAX_PATH );
190 memset(&actctx, 0, sizeof(ACTCTXW));
191 actctx.cbSize = sizeof(ACTCTXW);
192 actctx.lpSource = path;
194 handle = pCreateActCtxW(&actctx);
195 ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
197 ok(actctx.cbSize == sizeof(ACTCTXW), "actctx.cbSize=%d\n", actctx.cbSize);
198 ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
199 ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
200 ok(actctx.wProcessorArchitecture == 0, "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
201 ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId);
202 ok(actctx.lpAssemblyDirectory == NULL, "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
203 ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
204 ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n", actctx.lpApplicationName);
205 ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
207 DeleteFileA("file.manifest");
209 ret = pActivateActCtx(handle, cookie);
210 ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
212 return handle;
215 static const char actctx_manifest[] =
216 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
217 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
218 " publicKeyToken=\"6595b6414666f1df\" />"
219 "<file name=\"testlib.dll\">"
220 " <comClass description=\"Test com class\""
221 " clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
222 " progid=\"ProgId.ProgId\""
223 " miscStatusIcon=\"recomposeonresize\""
224 " />"
225 " <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb851}\""
226 " progid=\"CustomFont\""
227 " miscStatusIcon=\"recomposeonresize\""
228 " miscStatusContent=\"insideout\""
229 " />"
230 " <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
231 " progid=\"StdFont\""
232 " />"
233 "</file>"
234 "</assembly>";
236 DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
238 static void test_ProgIDFromCLSID(void)
240 ULONG_PTR cookie = 0;
241 LPWSTR progid;
242 HANDLE handle;
243 HRESULT hr;
245 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
246 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
247 if (hr == S_OK)
249 ok(!lstrcmpiW(progid, stdfont), "Didn't get expected prog ID\n");
250 CoTaskMemFree(progid);
253 progid = (LPWSTR)0xdeadbeef;
254 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
255 ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
256 ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
258 hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
259 ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
261 if ((handle = activate_context(actctx_manifest, &cookie)))
263 static const WCHAR customfontW[] = {'C','u','s','t','o','m','F','o','n','t',0};
265 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
266 todo_wine
267 ok(hr == S_OK, "got 0x%08x\n", hr);
268 if (hr == S_OK)
270 ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid));
271 CoTaskMemFree(progid);
274 /* try something registered and redirected */
275 progid = NULL;
276 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
277 ok(hr == S_OK, "got 0x%08x\n", hr);
278 todo_wine
279 ok(!lstrcmpiW(progid, customfontW), "got wrong progid %s\n", wine_dbgstr_w(progid));
280 CoTaskMemFree(progid);
282 pDeactivateActCtx(0, cookie);
283 pReleaseActCtx(handle);
287 static void test_CLSIDFromProgID(void)
289 ULONG_PTR cookie = 0;
290 HANDLE handle;
291 CLSID clsid;
292 HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
293 ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
294 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
296 hr = CLSIDFromString(stdfont, &clsid);
297 ok_ole_success(hr, "CLSIDFromString");
298 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
300 /* test some failure cases */
302 hr = CLSIDFromProgID(wszNonExistent, NULL);
303 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
305 hr = CLSIDFromProgID(NULL, &clsid);
306 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
308 memset(&clsid, 0xcc, sizeof(clsid));
309 hr = CLSIDFromProgID(wszNonExistent, &clsid);
310 ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
311 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
313 /* fails without proper context */
314 memset(&clsid, 0xcc, sizeof(clsid));
315 hr = CLSIDFromProgID(progidW, &clsid);
316 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
317 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "wrong clsid\n");
319 if ((handle = activate_context(actctx_manifest, &cookie)))
321 GUID clsid1;
323 clsid = CLSID_NULL;
324 hr = CLSIDFromProgID(progidW, &clsid);
325 todo_wine
326 ok(hr == S_OK, "got 0x%08x\n", hr);
327 if (hr == S_OK)
328 /* it returns generated CLSID here */
329 ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL),
330 "got wrong clsid %s\n", debugstr_guid(&clsid));
332 /* duplicate progid present in context - returns generated guid here too */
333 clsid = CLSID_NULL;
334 hr = CLSIDFromProgID(stdfont, &clsid);
335 ok(hr == S_OK, "got 0x%08x\n", hr);
336 clsid1 = CLSID_StdFont;
337 /* that's where it differs from StdFont */
338 clsid1.Data4[7] = 0x52;
339 todo_wine
340 ok(!IsEqualCLSID(&clsid, &CLSID_StdFont) && !IsEqualCLSID(&clsid, &CLSID_NULL) && !IsEqualCLSID(&clsid, &clsid1),
341 "got %s\n", debugstr_guid(&clsid));
343 pDeactivateActCtx(0, cookie);
344 pReleaseActCtx(handle);
348 static void test_CLSIDFromString(void)
350 CLSID clsid;
351 WCHAR wszCLSID_Broken[50];
352 UINT i;
354 HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
355 ok_ole_success(hr, "CLSIDFromString");
356 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
358 hr = CLSIDFromString(NULL, &clsid);
359 ok_ole_success(hr, "CLSIDFromString");
360 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
362 lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
363 for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
364 wszCLSID_Broken[i] = 'A';
365 wszCLSID_Broken[i] = '\0';
367 memset(&clsid, 0, sizeof(CLSID));
368 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
369 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
370 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
372 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
373 memset(&clsid, 0, sizeof(CLSID));
374 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
375 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
376 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
378 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
379 memset(&clsid, 0, sizeof(CLSID));
380 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
381 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
382 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
384 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
385 memset(&clsid, 0, sizeof(CLSID));
386 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
387 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
388 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
390 memset(&clsid, 0xcc, sizeof(CLSID));
391 hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
392 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
393 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
395 wszCLSID_Broken[9] = '*';
396 memset(&clsid, 0xcc, sizeof(CLSID));
397 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
398 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
399 ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
400 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
402 wszCLSID_Broken[3] = '*';
403 memset(&clsid, 0xcc, sizeof(CLSID));
404 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
405 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
406 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
407 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
409 wszCLSID_Broken[3] = '\0';
410 memset(&clsid, 0xcc, sizeof(CLSID));
411 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
412 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
413 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
414 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
417 static void test_StringFromGUID2(void)
419 WCHAR str[50];
420 int len;
422 /* invalid pointer */
423 SetLastError(0xdeadbeef);
424 len = StringFromGUID2(NULL,str,50);
425 ok(len == 0, "len: %d (expected 0)\n", len);
426 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
428 /* Test corner cases for buffer size */
429 len = StringFromGUID2(&CLSID_StdFont,str,50);
430 ok(len == 39, "len: %d (expected 39)\n", len);
431 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
433 memset(str,0,sizeof str);
434 len = StringFromGUID2(&CLSID_StdFont,str,39);
435 ok(len == 39, "len: %d (expected 39)\n", len);
436 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
438 len = StringFromGUID2(&CLSID_StdFont,str,38);
439 ok(len == 0, "len: %d (expected 0)\n", len);
441 len = StringFromGUID2(&CLSID_StdFont,str,30);
442 ok(len == 0, "len: %d (expected 0)\n", len);
445 struct info
447 HANDLE wait, stop;
450 static DWORD CALLBACK ole_initialize_thread(LPVOID pv)
452 HRESULT hr;
453 struct info *info = pv;
455 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
457 SetEvent(info->wait);
458 WaitForSingleObject(info->stop, 10000);
460 CoUninitialize();
461 return hr;
464 static void test_CoCreateInstance(void)
466 HRESULT hr;
467 HANDLE thread;
468 DWORD tid, exitcode;
469 IUnknown *pUnk;
470 struct info info;
471 REFCLSID rclsid = &CLSID_InternetZoneManager;
473 pUnk = (IUnknown *)0xdeadbeef;
474 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
475 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
476 ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
478 OleInitialize(NULL);
480 /* test errors returned for non-registered clsids */
481 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
482 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
483 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pUnk);
484 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
485 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (void **)&pUnk);
486 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
487 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_REMOTE_SERVER, &IID_IUnknown, (void **)&pUnk);
488 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
490 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
491 if(hr == REGDB_E_CLASSNOTREG)
493 skip("IE not installed so can't test CoCreateInstance\n");
494 OleUninitialize();
495 return;
498 ok_ole_success(hr, "CoCreateInstance");
499 if(pUnk) IUnknown_Release(pUnk);
500 OleUninitialize();
502 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
503 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
505 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
506 thread has already done so */
508 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
509 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
511 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
512 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
514 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
515 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
517 ok( !WaitForSingleObject(info.wait, 10000 ), "wait timed out\n" );
519 pUnk = (IUnknown *)0xdeadbeef;
520 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
521 ok(hr == S_OK, "CoCreateInstance should have returned S_OK instead of 0x%08x\n", hr);
522 if (pUnk) IUnknown_Release(pUnk);
524 SetEvent(info.stop);
525 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
527 GetExitCodeThread(thread, &exitcode);
528 hr = exitcode;
529 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
531 CloseHandle(thread);
532 CloseHandle(info.wait);
533 CloseHandle(info.stop);
536 static void test_CoGetClassObject(void)
538 HRESULT hr;
539 HANDLE thread;
540 DWORD tid, exitcode;
541 IUnknown *pUnk;
542 struct info info;
543 REFCLSID rclsid = &CLSID_InternetZoneManager;
544 HKEY hkey;
545 LONG res;
547 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
548 ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
549 ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
551 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
552 ok(hr == E_INVALIDARG ||
553 broken(hr == CO_E_NOTINITIALIZED), /* win9x */
554 "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
556 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
557 thread has already done so */
559 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
560 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
562 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
563 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
565 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
566 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
568 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
570 pUnk = (IUnknown *)0xdeadbeef;
571 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
572 if(hr == REGDB_E_CLASSNOTREG)
573 skip("IE not installed so can't test CoGetClassObject\n");
574 else
576 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
577 if (pUnk) IUnknown_Release(pUnk);
580 SetEvent(info.stop);
581 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
583 GetExitCodeThread(thread, &exitcode);
584 hr = exitcode;
585 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
587 CloseHandle(thread);
588 CloseHandle(info.wait);
589 CloseHandle(info.stop);
591 if (!pRegOverridePredefKey)
593 win_skip("RegOverridePredefKey not available\n");
594 return;
597 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
599 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
600 if (hr == S_OK)
602 IUnknown_Release(pUnk);
604 res = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
605 KEY_ALL_ACCESS, NULL, &hkey, NULL);
606 ok(!res, "RegCreateKeyEx returned %d\n", res);
608 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
609 ok(!res, "RegOverridePredefKey returned %d\n", res);
611 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
612 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
614 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
615 ok(!res, "RegOverridePredefKey returned %d\n", res);
617 if (hr == S_OK) IUnknown_Release(pUnk);
618 RegCloseKey(hkey);
620 CoUninitialize();
623 static ATOM register_dummy_class(void)
625 WNDCLASS wc =
628 DefWindowProc,
631 GetModuleHandle(NULL),
632 NULL,
633 LoadCursor(NULL, IDC_ARROW),
634 (HBRUSH)(COLOR_BTNFACE+1),
635 NULL,
636 TEXT("WineOleTestClass"),
639 return RegisterClass(&wc);
642 static void test_ole_menu(void)
644 HWND hwndFrame;
645 HRESULT hr;
647 hwndFrame = CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
648 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
649 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
651 DestroyWindow(hwndFrame);
655 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
657 if (ppvObj == NULL) return E_POINTER;
659 if (IsEqualGUID(riid, &IID_IUnknown) ||
660 IsEqualGUID(riid, &IID_IClassFactory))
662 *ppvObj = iface;
663 IMessageFilter_AddRef(iface);
664 return S_OK;
667 return E_NOINTERFACE;
670 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
672 return 2; /* non-heap object */
675 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
677 return 1; /* non-heap object */
680 static DWORD WINAPI MessageFilter_HandleInComingCall(
681 IMessageFilter *iface,
682 DWORD dwCallType,
683 HTASK threadIDCaller,
684 DWORD dwTickCount,
685 LPINTERFACEINFO lpInterfaceInfo)
687 trace("HandleInComingCall\n");
688 return SERVERCALL_ISHANDLED;
691 static DWORD WINAPI MessageFilter_RetryRejectedCall(
692 IMessageFilter *iface,
693 HTASK threadIDCallee,
694 DWORD dwTickCount,
695 DWORD dwRejectType)
697 trace("RetryRejectedCall\n");
698 return 0;
701 static DWORD WINAPI MessageFilter_MessagePending(
702 IMessageFilter *iface,
703 HTASK threadIDCallee,
704 DWORD dwTickCount,
705 DWORD dwPendingType)
707 trace("MessagePending\n");
708 return PENDINGMSG_WAITNOPROCESS;
711 static const IMessageFilterVtbl MessageFilter_Vtbl =
713 MessageFilter_QueryInterface,
714 MessageFilter_AddRef,
715 MessageFilter_Release,
716 MessageFilter_HandleInComingCall,
717 MessageFilter_RetryRejectedCall,
718 MessageFilter_MessagePending
721 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
723 static void test_CoRegisterMessageFilter(void)
725 HRESULT hr;
726 IMessageFilter *prev_filter;
728 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
729 ok(hr == CO_E_NOT_SUPPORTED,
730 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
731 hr);
733 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
734 prev_filter = (IMessageFilter *)0xdeadbeef;
735 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
736 ok(hr == CO_E_NOT_SUPPORTED,
737 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
738 hr);
739 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
740 "prev_filter should have been set to %p\n", prev_filter);
741 CoUninitialize();
743 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
745 hr = CoRegisterMessageFilter(NULL, NULL);
746 ok_ole_success(hr, "CoRegisterMessageFilter");
748 prev_filter = (IMessageFilter *)0xdeadbeef;
749 hr = CoRegisterMessageFilter(NULL, &prev_filter);
750 ok_ole_success(hr, "CoRegisterMessageFilter");
751 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
753 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
754 ok_ole_success(hr, "CoRegisterMessageFilter");
755 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
757 hr = CoRegisterMessageFilter(NULL, NULL);
758 ok_ole_success(hr, "CoRegisterMessageFilter");
760 CoUninitialize();
763 static HRESULT WINAPI Test_IUnknown_QueryInterface(
764 IUnknown *iface,
765 REFIID riid,
766 LPVOID *ppvObj)
768 if (ppvObj == NULL) return E_POINTER;
770 if (IsEqualIID(riid, &IID_IUnknown) ||
771 IsEqualIID(riid, &IID_IWineTest))
773 *ppvObj = iface;
774 IUnknown_AddRef(iface);
775 return S_OK;
778 *ppvObj = NULL;
779 return E_NOINTERFACE;
782 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
784 return 2; /* non-heap-based object */
787 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
789 return 1; /* non-heap-based object */
792 static const IUnknownVtbl TestUnknown_Vtbl =
794 Test_IUnknown_QueryInterface,
795 Test_IUnknown_AddRef,
796 Test_IUnknown_Release,
799 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
801 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
802 IPSFactoryBuffer * This,
803 /* [in] */ REFIID riid,
804 /* [iid_is][out] */ void **ppvObject)
806 if (IsEqualIID(riid, &IID_IUnknown) ||
807 IsEqualIID(riid, &IID_IPSFactoryBuffer))
809 *ppvObject = This;
810 IPSFactoryBuffer_AddRef(This);
811 return S_OK;
813 return E_NOINTERFACE;
816 static ULONG WINAPI PSFactoryBuffer_AddRef(
817 IPSFactoryBuffer * This)
819 return 2;
822 static ULONG WINAPI PSFactoryBuffer_Release(
823 IPSFactoryBuffer * This)
825 return 1;
828 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
829 IPSFactoryBuffer * This,
830 /* [in] */ IUnknown *pUnkOuter,
831 /* [in] */ REFIID riid,
832 /* [out] */ IRpcProxyBuffer **ppProxy,
833 /* [out] */ void **ppv)
835 return E_NOTIMPL;
838 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
839 IPSFactoryBuffer * This,
840 /* [in] */ REFIID riid,
841 /* [unique][in] */ IUnknown *pUnkServer,
842 /* [out] */ IRpcStubBuffer **ppStub)
844 return E_NOTIMPL;
847 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
849 PSFactoryBuffer_QueryInterface,
850 PSFactoryBuffer_AddRef,
851 PSFactoryBuffer_Release,
852 PSFactoryBuffer_CreateProxy,
853 PSFactoryBuffer_CreateStub
856 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
858 static const CLSID CLSID_WineTestPSFactoryBuffer =
860 0x52011640,
861 0x8164,
862 0x4fd0,
863 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
864 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
866 static void test_CoRegisterPSClsid(void)
868 HRESULT hr;
869 DWORD dwRegistrationKey;
870 IStream *stream;
871 CLSID clsid;
873 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
874 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
876 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
878 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
879 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
880 ok_ole_success(hr, "CoRegisterClassObject");
882 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
883 ok_ole_success(hr, "CoRegisterPSClsid");
885 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
886 ok_ole_success(hr, "CreateStreamOnHGlobal");
888 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
889 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
890 IStream_Release(stream);
892 hr = CoRevokeClassObject(dwRegistrationKey);
893 ok_ole_success(hr, "CoRevokeClassObject");
895 CoUninitialize();
897 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
899 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
900 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
902 CoUninitialize();
905 static void test_CoGetPSClsid(void)
907 HRESULT hr;
908 CLSID clsid;
909 HKEY hkey;
910 LONG res;
912 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
913 ok(hr == CO_E_NOTINITIALIZED,
914 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
915 hr);
917 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
919 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
920 ok_ole_success(hr, "CoGetPSClsid");
922 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
923 ok(hr == REGDB_E_IIDNOTREG,
924 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
925 hr);
927 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
928 ok(hr == E_INVALIDARG,
929 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
930 hr);
932 if (!pRegOverridePredefKey)
934 win_skip("RegOverridePredefKey not available\n");
935 CoUninitialize();
936 return;
938 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
939 ok_ole_success(hr, "CoGetPSClsid");
941 res = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
942 KEY_ALL_ACCESS, NULL, &hkey, NULL);
943 ok(!res, "RegCreateKeyEx returned %d\n", res);
945 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
946 ok(!res, "RegOverridePredefKey returned %d\n", res);
948 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
949 ok_ole_success(hr, "CoGetPSClsid");
951 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
952 ok(!res, "RegOverridePredefKey returned %d\n", res);
954 RegCloseKey(hkey);
955 CoUninitialize();
958 /* basic test, mainly for invalid arguments. see marshal.c for more */
959 static void test_CoUnmarshalInterface(void)
961 IUnknown *pProxy;
962 IStream *pStream;
963 HRESULT hr;
965 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
966 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
968 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
969 ok_ole_success(hr, "CreateStreamOnHGlobal");
971 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
972 todo_wine
973 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
975 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
977 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
978 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
980 CoUninitialize();
982 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
983 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
985 IStream_Release(pStream);
988 static void test_CoGetInterfaceAndReleaseStream(void)
990 HRESULT hr;
991 IUnknown *pUnk;
993 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
995 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
996 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
998 CoUninitialize();
1001 /* basic test, mainly for invalid arguments. see marshal.c for more */
1002 static void test_CoMarshalInterface(void)
1004 IStream *pStream;
1005 HRESULT hr;
1006 static const LARGE_INTEGER llZero;
1008 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1010 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1011 ok_ole_success(hr, "CreateStreamOnHGlobal");
1013 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1014 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1016 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1017 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1019 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1020 ok_ole_success(hr, "CoMarshalInterface");
1022 /* stream not rewound */
1023 hr = CoReleaseMarshalData(pStream);
1024 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1026 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1027 ok_ole_success(hr, "IStream_Seek");
1029 hr = CoReleaseMarshalData(pStream);
1030 ok_ole_success(hr, "CoReleaseMarshalData");
1032 IStream_Release(pStream);
1034 CoUninitialize();
1037 static void test_CoMarshalInterThreadInterfaceInStream(void)
1039 IStream *pStream;
1040 HRESULT hr;
1041 IClassFactory *pProxy;
1043 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1045 cLocks = 0;
1047 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
1048 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1050 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
1051 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1053 ok_no_locks();
1055 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
1056 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
1058 ok_more_than_one_lock();
1060 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1061 ok_ole_success(hr, "CoUnmarshalInterface");
1063 IClassFactory_Release(pProxy);
1064 IStream_Release(pStream);
1066 ok_no_locks();
1068 CoUninitialize();
1071 static void test_CoRegisterClassObject(void)
1073 DWORD cookie;
1074 HRESULT hr;
1075 IClassFactory *pcf;
1077 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1079 /* CLSCTX_INPROC_SERVER */
1080 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1081 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1082 ok_ole_success(hr, "CoRegisterClassObject");
1083 hr = CoRevokeClassObject(cookie);
1084 ok_ole_success(hr, "CoRevokeClassObject");
1086 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1087 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1088 ok_ole_success(hr, "CoRegisterClassObject");
1089 hr = CoRevokeClassObject(cookie);
1090 ok_ole_success(hr, "CoRevokeClassObject");
1092 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1093 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1094 ok_ole_success(hr, "CoRegisterClassObject");
1095 hr = CoRevokeClassObject(cookie);
1096 ok_ole_success(hr, "CoRevokeClassObject");
1098 /* CLSCTX_LOCAL_SERVER */
1099 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1100 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1101 ok_ole_success(hr, "CoRegisterClassObject");
1102 hr = CoRevokeClassObject(cookie);
1103 ok_ole_success(hr, "CoRevokeClassObject");
1105 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1106 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1107 ok_ole_success(hr, "CoRegisterClassObject");
1108 hr = CoRevokeClassObject(cookie);
1109 ok_ole_success(hr, "CoRevokeClassObject");
1111 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1112 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1113 ok_ole_success(hr, "CoRegisterClassObject");
1114 hr = CoRevokeClassObject(cookie);
1115 ok_ole_success(hr, "CoRevokeClassObject");
1117 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
1118 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1119 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1120 ok_ole_success(hr, "CoRegisterClassObject");
1121 hr = CoRevokeClassObject(cookie);
1122 ok_ole_success(hr, "CoRevokeClassObject");
1124 /* test whether an object that doesn't support IClassFactory can be
1125 * registered for CLSCTX_LOCAL_SERVER */
1126 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
1127 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1128 ok_ole_success(hr, "CoRegisterClassObject");
1129 hr = CoRevokeClassObject(cookie);
1130 ok_ole_success(hr, "CoRevokeClassObject");
1132 /* test whether registered class becomes invalid when apartment is destroyed */
1133 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1134 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1135 ok_ole_success(hr, "CoRegisterClassObject");
1137 CoUninitialize();
1138 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1140 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
1141 &IID_IClassFactory, (void **)&pcf);
1142 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
1144 /* crashes with at least win9x DCOM! */
1145 if (0)
1146 CoRevokeClassObject(cookie);
1148 CoUninitialize();
1151 static HRESULT get_class_object(CLSCTX clsctx)
1153 HRESULT hr;
1154 IClassFactory *pcf;
1156 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1157 (void **)&pcf);
1159 if (SUCCEEDED(hr))
1160 IClassFactory_Release(pcf);
1162 return hr;
1165 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1167 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1168 HRESULT hr;
1170 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1172 hr = get_class_object(clsctx);
1174 CoUninitialize();
1176 return hr;
1179 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1181 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1182 HRESULT hr;
1183 IClassFactory *pcf;
1184 IMultiQI *pMQI;
1186 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1188 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1189 (void **)&pcf);
1191 if (SUCCEEDED(hr))
1193 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1194 if (SUCCEEDED(hr))
1195 IMultiQI_Release(pMQI);
1196 IClassFactory_Release(pcf);
1199 CoUninitialize();
1201 return hr;
1204 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1206 HRESULT hr;
1207 DWORD cookie;
1209 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1211 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1212 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1214 CoUninitialize();
1216 return hr;
1219 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1221 DWORD cookie = (DWORD_PTR)pv;
1222 HRESULT hr;
1224 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1226 hr = CoRevokeClassObject(cookie);
1228 CoUninitialize();
1230 return hr;
1233 static void test_registered_object_thread_affinity(void)
1235 HRESULT hr;
1236 DWORD cookie;
1237 HANDLE thread;
1238 DWORD tid;
1239 DWORD exitcode;
1241 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1243 /* CLSCTX_INPROC_SERVER */
1245 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1246 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1247 ok_ole_success(hr, "CoRegisterClassObject");
1249 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1250 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1251 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1252 GetExitCodeThread(thread, &exitcode);
1253 hr = exitcode;
1254 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1255 "registered in different thread should return REGDB_E_CLASSNOTREG "
1256 "instead of 0x%08x\n", hr);
1258 hr = get_class_object(CLSCTX_INPROC_SERVER);
1259 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1260 "thread should return S_OK instead of 0x%08x\n", hr);
1262 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1263 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1264 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1265 GetExitCodeThread(thread, &exitcode);
1266 hr = exitcode;
1267 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1269 hr = CoRevokeClassObject(cookie);
1270 ok_ole_success(hr, "CoRevokeClassObject");
1272 /* CLSCTX_LOCAL_SERVER */
1274 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1275 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1276 ok_ole_success(hr, "CoRegisterClassObject");
1278 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1279 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1280 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1282 MSG msg;
1283 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1285 TranslateMessage(&msg);
1286 DispatchMessageA(&msg);
1289 GetExitCodeThread(thread, &exitcode);
1290 hr = exitcode;
1291 ok(hr == S_OK, "CoGetClassObject on local server object "
1292 "registered in different thread should return S_OK "
1293 "instead of 0x%08x\n", hr);
1295 hr = get_class_object(CLSCTX_LOCAL_SERVER);
1296 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1297 "thread should return S_OK instead of 0x%08x\n", hr);
1299 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid);
1300 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1301 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1302 GetExitCodeThread(thread, &exitcode);
1303 hr = exitcode;
1304 ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different "
1305 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1307 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1308 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1309 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1310 GetExitCodeThread(thread, &exitcode);
1311 hr = exitcode;
1312 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1313 "thread should return S_OK instead of 0x%08x\n", hr);
1315 hr = CoRevokeClassObject(cookie);
1316 ok_ole_success(hr, "CoRevokeClassObject");
1318 CoUninitialize();
1321 static DWORD CALLBACK free_libraries_thread(LPVOID p)
1323 CoFreeUnusedLibraries();
1324 return 0;
1327 static inline BOOL is_module_loaded(const char *module)
1329 return GetModuleHandle(module) != 0;
1332 static void test_CoFreeUnusedLibraries(void)
1334 HRESULT hr;
1335 IUnknown *pUnk;
1336 DWORD tid;
1337 HANDLE thread;
1339 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1341 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1343 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1344 if (hr == REGDB_E_CLASSNOTREG)
1346 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1347 CoUninitialize();
1348 return;
1350 ok_ole_success(hr, "CoCreateInstance");
1352 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1354 ok(pUnk != NULL ||
1355 broken(pUnk == NULL), /* win9x */
1356 "Expected a valid pointer\n");
1357 if (pUnk)
1358 IUnknown_Release(pUnk);
1360 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1362 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1363 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1364 CloseHandle(thread);
1366 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1368 CoFreeUnusedLibraries();
1370 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1372 CoUninitialize();
1375 static void test_CoGetObjectContext(void)
1377 HRESULT hr;
1378 ULONG refs;
1379 IComThreadingInfo *pComThreadingInfo;
1380 IContextCallback *pContextCallback;
1381 IObjContext *pObjContext;
1382 APTTYPE apttype;
1383 THDTYPE thdtype;
1384 struct info info;
1385 HANDLE thread;
1386 DWORD tid, exitcode;
1388 if (!pCoGetObjectContext)
1390 skip("CoGetObjectContext not present\n");
1391 return;
1394 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1395 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1396 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1398 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1399 thread has already done so */
1401 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
1402 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1404 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
1405 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1407 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1408 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1410 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1412 pComThreadingInfo = NULL;
1413 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1414 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1415 IComThreadingInfo_Release(pComThreadingInfo);
1417 SetEvent(info.stop);
1418 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1420 GetExitCodeThread(thread, &exitcode);
1421 hr = exitcode;
1422 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1424 CloseHandle(thread);
1425 CloseHandle(info.wait);
1426 CloseHandle(info.stop);
1428 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1430 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1431 ok_ole_success(hr, "CoGetObjectContext");
1433 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1434 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1435 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1437 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1438 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1439 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1441 refs = IComThreadingInfo_Release(pComThreadingInfo);
1442 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1444 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1445 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1447 if (hr == S_OK)
1449 refs = IContextCallback_Release(pContextCallback);
1450 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1453 CoUninitialize();
1455 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1457 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1458 ok_ole_success(hr, "CoGetObjectContext");
1460 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1461 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1462 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1464 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1465 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1466 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1468 refs = IComThreadingInfo_Release(pComThreadingInfo);
1469 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1471 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1472 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1474 if (hr == S_OK)
1476 refs = IContextCallback_Release(pContextCallback);
1477 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1480 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1481 ok_ole_success(hr, "CoGetObjectContext");
1483 refs = IObjContext_Release(pObjContext);
1484 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
1486 CoUninitialize();
1489 typedef struct {
1490 IUnknown IUnknown_iface;
1491 LONG refs;
1492 } Test_CallContext;
1494 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
1496 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
1499 static HRESULT WINAPI Test_CallContext_QueryInterface(
1500 IUnknown *iface,
1501 REFIID riid,
1502 LPVOID *ppvObj)
1504 if (ppvObj == NULL) return E_POINTER;
1506 if (IsEqualGUID(riid, &IID_IUnknown))
1508 *ppvObj = iface;
1509 IUnknown_AddRef(iface);
1510 return S_OK;
1513 *ppvObj = NULL;
1514 return E_NOINTERFACE;
1517 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
1519 Test_CallContext *This = impl_from_IUnknown(iface);
1520 return InterlockedIncrement(&This->refs);
1523 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
1525 Test_CallContext *This = impl_from_IUnknown(iface);
1526 ULONG refs = InterlockedDecrement(&This->refs);
1527 if (!refs)
1528 HeapFree(GetProcessHeap(), 0, This);
1529 return refs;
1532 static const IUnknownVtbl TestCallContext_Vtbl =
1534 Test_CallContext_QueryInterface,
1535 Test_CallContext_AddRef,
1536 Test_CallContext_Release
1539 static void test_CoGetCallContext(void)
1541 HRESULT hr;
1542 ULONG refs;
1543 IUnknown *pUnk;
1544 Test_CallContext *test_object;
1546 if (!pCoSwitchCallContext)
1548 skip("CoSwitchCallContext not present\n");
1549 return;
1552 CoInitialize(NULL);
1554 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
1555 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
1556 test_object->refs = 1;
1558 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1559 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1561 pUnk = (IUnknown*)0xdeadbeef;
1562 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
1563 ok_ole_success(hr, "CoSwitchCallContext");
1564 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
1565 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1566 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1567 IUnknown_Release(&test_object->IUnknown_iface);
1569 pUnk = (IUnknown*)0xdeadbeef;
1570 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1571 ok_ole_success(hr, "CoGetCallContext");
1572 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1573 &test_object->IUnknown_iface, pUnk);
1574 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1575 ok(refs == 3, "Expected refcount 3, got %d\n", refs);
1576 IUnknown_Release(&test_object->IUnknown_iface);
1577 IUnknown_Release(pUnk);
1579 pUnk = (IUnknown*)0xdeadbeef;
1580 hr = pCoSwitchCallContext(NULL, &pUnk);
1581 ok_ole_success(hr, "CoSwitchCallContext");
1582 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1583 &test_object->IUnknown_iface, pUnk);
1584 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1585 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1586 IUnknown_Release(&test_object->IUnknown_iface);
1588 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1589 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1591 IUnknown_Release(&test_object->IUnknown_iface);
1593 CoUninitialize();
1596 static void test_CoGetContextToken(void)
1598 HRESULT hr;
1599 ULONG refs;
1600 ULONG_PTR token;
1601 IObjContext *ctx;
1602 struct info info;
1603 HANDLE thread;
1604 DWORD tid, exitcode;
1606 if (!pCoGetContextToken)
1608 win_skip("CoGetContextToken not present\n");
1609 return;
1612 token = 0xdeadbeef;
1613 hr = pCoGetContextToken(&token);
1614 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
1615 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
1617 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1618 thread has already done so */
1620 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
1621 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1623 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
1624 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1626 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1627 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1629 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1631 token = 0;
1632 hr = pCoGetContextToken(&token);
1633 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1635 SetEvent(info.stop);
1636 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1638 GetExitCodeThread(thread, &exitcode);
1639 hr = exitcode;
1640 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1642 CloseHandle(thread);
1643 CloseHandle(info.wait);
1644 CloseHandle(info.stop);
1646 CoInitialize(NULL);
1648 hr = pCoGetContextToken(NULL);
1649 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
1651 token = 0;
1652 hr = pCoGetContextToken(&token);
1653 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1654 ok(token, "Expected token != 0\n");
1656 refs = IUnknown_AddRef((IUnknown *)token);
1657 todo_wine ok(refs == 1, "Expected 1, got %u\n", refs);
1659 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
1660 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1661 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1663 refs = IUnknown_AddRef((IUnknown *)ctx);
1664 todo_wine ok(refs == 3, "Expected 3, got %u\n", refs);
1666 refs = IUnknown_Release((IUnknown *)ctx);
1667 todo_wine ok(refs == 2, "Expected 2, got %u\n", refs);
1669 refs = IUnknown_Release((IUnknown *)token);
1670 ok(refs == 1, "Expected 1, got %u\n", refs);
1672 /* CoGetContextToken does not add a reference */
1673 token = 0;
1674 hr = pCoGetContextToken(&token);
1675 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1676 ok(token, "Expected token != 0\n");
1677 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1679 refs = IUnknown_AddRef((IUnknown *)ctx);
1680 ok(refs == 2, "Expected 1, got %u\n", refs);
1682 refs = IUnknown_Release((IUnknown *)ctx);
1683 ok(refs == 1, "Expected 0, got %u\n", refs);
1685 refs = IUnknown_Release((IUnknown *)ctx);
1686 ok(refs == 0, "Expected 0, got %u\n", refs);
1688 CoUninitialize();
1691 static void test_CoGetTreatAsClass(void)
1693 HRESULT hr;
1694 CLSID out;
1695 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1697 if (!pCoGetTreatAsClass)
1699 win_skip("CoGetTreatAsClass not present\n");
1700 return;
1702 hr = pCoGetTreatAsClass(&deadbeef,&out);
1703 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
1704 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
1707 static void test_CoInitializeEx(void)
1709 HRESULT hr;
1711 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1712 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
1714 /* Calling OleInitialize for the first time should yield S_OK even with
1715 * apartment already initialized by previous CoInitialize(Ex) calls. */
1716 hr = OleInitialize(NULL);
1717 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
1719 /* Subsequent calls to OleInitialize should return S_FALSE */
1720 hr = OleInitialize(NULL);
1721 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
1723 /* Cleanup */
1724 CoUninitialize();
1725 OleUninitialize();
1728 static void test_OleRegGetMiscStatus(void)
1730 ULONG_PTR cookie;
1731 HANDLE handle;
1732 DWORD status;
1733 HRESULT hr;
1735 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, NULL);
1736 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1738 status = 0xdeadbeef;
1739 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
1740 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
1741 ok(status == 0, "got 0x%08x\n", status);
1743 status = -1;
1744 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
1745 ok(hr == S_OK, "got 0x%08x\n", hr);
1746 ok(status == 0, "got 0x%08x\n", status);
1748 if ((handle = activate_context(actctx_manifest, &cookie)))
1750 status = 0;
1751 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
1752 todo_wine {
1753 ok(hr == S_OK, "got 0x%08x\n", hr);
1754 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
1756 /* context data takes precedence over registration info */
1757 status = 0;
1758 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
1759 ok(hr == S_OK, "got 0x%08x\n", hr);
1760 todo_wine
1761 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
1763 /* there's no such attribute in context */
1764 status = -1;
1765 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status);
1766 todo_wine
1767 ok(hr == S_OK, "got 0x%08x\n", hr);
1768 ok(status == 0, "got 0x%08x\n", status);
1770 pDeactivateActCtx(0, cookie);
1771 pReleaseActCtx(handle);
1775 static void init_funcs(void)
1777 HMODULE hOle32 = GetModuleHandleA("ole32");
1778 HMODULE hAdvapi32 = GetModuleHandleA("advapi32");
1779 HMODULE hkernel32 = GetModuleHandleA("kernel32");
1781 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
1782 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
1783 pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
1784 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
1785 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
1786 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
1788 pActivateActCtx = (void*)GetProcAddress(hkernel32, "ActivateActCtx");
1789 pCreateActCtxW = (void*)GetProcAddress(hkernel32, "CreateActCtxW");
1790 pDeactivateActCtx = (void*)GetProcAddress(hkernel32, "DeactivateActCtx");
1791 pReleaseActCtx = (void*)GetProcAddress(hkernel32, "ReleaseActCtx");
1794 START_TEST(compobj)
1796 init_funcs();
1798 if (!pCoInitializeEx)
1800 trace("You need DCOM95 installed to run this test\n");
1801 return;
1804 test_ProgIDFromCLSID();
1805 test_CLSIDFromProgID();
1806 test_CLSIDFromString();
1807 test_StringFromGUID2();
1808 test_CoCreateInstance();
1809 test_ole_menu();
1810 test_CoGetClassObject();
1811 test_CoRegisterMessageFilter();
1812 test_CoRegisterPSClsid();
1813 test_CoGetPSClsid();
1814 test_CoUnmarshalInterface();
1815 test_CoGetInterfaceAndReleaseStream();
1816 test_CoMarshalInterface();
1817 test_CoMarshalInterThreadInterfaceInStream();
1818 test_CoRegisterClassObject();
1819 test_registered_object_thread_affinity();
1820 test_CoFreeUnusedLibraries();
1821 test_CoGetObjectContext();
1822 test_CoGetCallContext();
1823 test_CoGetContextToken();
1824 test_CoGetTreatAsClass();
1825 test_CoInitializeEx();
1826 test_OleRegGetMiscStatus();