ole32/tests: Add tests for CoWaitForMultipleHandles.
[wine.git] / dlls / ole32 / tests / compobj.c
blobf87977315cbf6d127ee9fa147c7ad64ec775d20b
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 */
34 #include "dde.h"
36 #include "ctxtcall.h"
38 #include "wine/test.h"
40 /* functions that are not present on all versions of Windows */
41 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
42 static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
43 static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
44 static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
45 static HRESULT (WINAPI * pCoTreatAsClass)(REFCLSID clsidOld, REFCLSID pClsidNew);
46 static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
47 static LONG (WINAPI * pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
48 static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
50 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
51 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
52 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
53 static BOOL (WINAPI *pIsWow64Process)(HANDLE, LPBOOL);
54 static void (WINAPI *pReleaseActCtx)(HANDLE);
56 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
57 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
58 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
60 static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
61 static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
62 static const GUID IID_Testiface = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
63 static const GUID IID_Testiface2 = { 0x32222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
64 static const GUID IID_Testiface3 = { 0x42222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
65 static const GUID IID_Testiface4 = { 0x52222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
66 static const GUID IID_Testiface5 = { 0x62222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
67 static const GUID IID_Testiface6 = { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
68 static const GUID IID_TestPS = { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } };
70 DEFINE_GUID(CLSID_InProcFreeMarshaler, 0x0000033a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
72 static const WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
73 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
74 static const WCHAR wszCLSID_StdFont[] =
76 '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
77 '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
79 static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
80 static const WCHAR cf_brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
81 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0};
83 DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
84 DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
86 static LONG cLocks;
88 static void LockModule(void)
90 InterlockedIncrement(&cLocks);
93 static void UnlockModule(void)
95 InterlockedDecrement(&cLocks);
98 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
99 LPCLASSFACTORY iface,
100 REFIID riid,
101 LPVOID *ppvObj)
103 if (ppvObj == NULL) return E_POINTER;
105 if (IsEqualGUID(riid, &IID_IUnknown) ||
106 IsEqualGUID(riid, &IID_IClassFactory))
108 *ppvObj = iface;
109 IClassFactory_AddRef(iface);
110 return S_OK;
113 *ppvObj = NULL;
114 return E_NOINTERFACE;
117 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
119 LockModule();
120 return 2; /* non-heap-based object */
123 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
125 UnlockModule();
126 return 1; /* non-heap-based object */
129 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
130 LPCLASSFACTORY iface,
131 IUnknown *pUnkOuter,
132 REFIID riid,
133 LPVOID *ppvObj)
135 *ppvObj = NULL;
136 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
137 return E_NOINTERFACE;
140 static HRESULT WINAPI Test_IClassFactory_LockServer(
141 LPCLASSFACTORY iface,
142 BOOL fLock)
144 return S_OK;
147 static const IClassFactoryVtbl TestClassFactory_Vtbl =
149 Test_IClassFactory_QueryInterface,
150 Test_IClassFactory_AddRef,
151 Test_IClassFactory_Release,
152 Test_IClassFactory_CreateInstance,
153 Test_IClassFactory_LockServer
156 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
158 static WCHAR manifest_path[MAX_PATH];
160 static BOOL create_manifest_file(const char *filename, const char *manifest)
162 int manifest_len;
163 DWORD size;
164 HANDLE file;
165 WCHAR path[MAX_PATH];
167 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
168 GetFullPathNameW(path, sizeof(manifest_path)/sizeof(WCHAR), manifest_path, NULL);
170 manifest_len = strlen(manifest);
171 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
172 FILE_ATTRIBUTE_NORMAL, NULL);
173 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
174 if(file == INVALID_HANDLE_VALUE)
175 return FALSE;
176 WriteFile(file, manifest, manifest_len, &size, NULL);
177 CloseHandle(file);
179 return TRUE;
182 static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie)
184 WCHAR path[MAX_PATH];
185 ACTCTXW actctx;
186 HANDLE handle;
187 BOOL ret;
189 if (!pCreateActCtxW) return NULL;
191 create_manifest_file("file.manifest", manifest);
193 MultiByteToWideChar( CP_ACP, 0, "file.manifest", -1, path, MAX_PATH );
194 memset(&actctx, 0, sizeof(ACTCTXW));
195 actctx.cbSize = sizeof(ACTCTXW);
196 actctx.lpSource = path;
198 handle = pCreateActCtxW(&actctx);
199 ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* some old XP/2k3 versions */,
200 "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
201 if (handle == INVALID_HANDLE_VALUE)
203 win_skip("activation context generation failed, some tests will be skipped\n");
204 handle = NULL;
207 ok(actctx.cbSize == sizeof(ACTCTXW), "actctx.cbSize=%d\n", actctx.cbSize);
208 ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
209 ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
210 ok(actctx.wProcessorArchitecture == 0, "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
211 ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId);
212 ok(actctx.lpAssemblyDirectory == NULL, "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
213 ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
214 ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n", actctx.lpApplicationName);
215 ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
217 DeleteFileA("file.manifest");
219 if (handle)
221 ret = pActivateActCtx(handle, cookie);
222 ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
225 return handle;
228 static const char actctx_manifest[] =
229 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
230 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
231 " publicKeyToken=\"6595b6414666f1df\" />"
232 "<file name=\"testlib.dll\">"
233 " <comClass"
234 " clsid=\"{0000033a-0000-0000-c000-000000000046}\""
235 " progid=\"FTMarshal\""
236 " />"
237 " <comClass"
238 " clsid=\"{5201163f-8164-4fd0-a1a2-5d5a3654d3bd}\""
239 " progid=\"WineOOPTest\""
240 " />"
241 " <comClass description=\"Test com class\""
242 " clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
243 " progid=\"ProgId.ProgId\""
244 " miscStatusIcon=\"recomposeonresize\""
245 " />"
246 " <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb851}\""
247 " progid=\"CustomFont\""
248 " miscStatusIcon=\"recomposeonresize\""
249 " miscStatusContent=\"insideout\""
250 " />"
251 " <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
252 " progid=\"StdFont\""
253 " />"
254 " <comClass clsid=\"{62222222-1234-1234-1234-56789abcdef0}\" >"
255 " <progid>ProgId.ProgId.1</progid>"
256 " </comClass>"
257 " <comInterfaceProxyStub "
258 " name=\"Iifaceps\""
259 " iid=\"{22222222-1234-1234-1234-56789abcdef0}\""
260 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
261 " />"
262 "</file>"
263 " <comInterfaceExternalProxyStub "
264 " name=\"Iifaceps2\""
265 " iid=\"{32222222-1234-1234-1234-56789abcdef0}\""
266 " />"
267 " <comInterfaceExternalProxyStub "
268 " name=\"Iifaceps3\""
269 " iid=\"{42222222-1234-1234-1234-56789abcdef0}\""
270 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
271 " />"
272 " <comInterfaceExternalProxyStub "
273 " name=\"Iifaceps4\""
274 " iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
275 " proxyStubClsid32=\"{00000000-0000-0000-0000-000000000000}\""
276 " />"
277 " <clrClass "
278 " clsid=\"{72222222-1234-1234-1234-56789abcdef0}\""
279 " name=\"clrclass\""
280 " >"
281 " <progid>clrprogid.1</progid>"
282 " </clrClass>"
283 "</assembly>";
285 DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
287 static void test_ProgIDFromCLSID(void)
289 ULONG_PTR cookie = 0;
290 LPWSTR progid;
291 HANDLE handle;
292 HRESULT hr;
294 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
295 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
296 if (hr == S_OK)
298 ok(!lstrcmpiW(progid, stdfont), "Didn't get expected prog ID\n");
299 CoTaskMemFree(progid);
302 progid = (LPWSTR)0xdeadbeef;
303 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
304 ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
305 ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
307 hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
308 ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
310 if ((handle = activate_context(actctx_manifest, &cookie)))
312 static const WCHAR customfontW[] = {'C','u','s','t','o','m','F','o','n','t',0};
314 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
315 ok(hr == S_OK, "got 0x%08x\n", hr);
316 ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid));
317 CoTaskMemFree(progid);
319 /* try something registered and redirected */
320 progid = NULL;
321 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
322 ok(hr == S_OK, "got 0x%08x\n", hr);
323 ok(!lstrcmpiW(progid, customfontW), "got wrong progid %s\n", wine_dbgstr_w(progid));
324 CoTaskMemFree(progid);
326 /* classes without default progid, progid list is not used */
327 hr = ProgIDFromCLSID(&IID_Testiface5, &progid);
328 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
330 hr = ProgIDFromCLSID(&IID_Testiface6, &progid);
331 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
333 pDeactivateActCtx(0, cookie);
334 pReleaseActCtx(handle);
338 static void test_CLSIDFromProgID(void)
340 ULONG_PTR cookie = 0;
341 HANDLE handle;
342 CLSID clsid;
343 HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
344 ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
345 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
347 hr = CLSIDFromString(stdfont, &clsid);
348 ok_ole_success(hr, "CLSIDFromString");
349 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
351 /* test some failure cases */
353 hr = CLSIDFromProgID(wszNonExistent, NULL);
354 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
356 hr = CLSIDFromProgID(NULL, &clsid);
357 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
359 memset(&clsid, 0xcc, sizeof(clsid));
360 hr = CLSIDFromProgID(wszNonExistent, &clsid);
361 ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
362 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
364 /* fails without proper context */
365 memset(&clsid, 0xcc, sizeof(clsid));
366 hr = CLSIDFromProgID(progidW, &clsid);
367 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
368 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "wrong clsid\n");
370 if ((handle = activate_context(actctx_manifest, &cookie)))
372 GUID clsid1;
374 memset(&clsid, 0xcc, sizeof(clsid));
375 hr = CLSIDFromProgID(wszNonExistent, &clsid);
376 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
377 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "should have zero CLSID on failure\n");
379 /* CLSIDFromString() doesn't check activation context */
380 hr = CLSIDFromString(progidW, &clsid);
381 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
383 clsid = CLSID_NULL;
384 hr = CLSIDFromProgID(progidW, &clsid);
385 /* it returns generated CLSID here */
386 ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL),
387 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid));
389 /* duplicate progid present in context - returns generated guid here too */
390 clsid = CLSID_NULL;
391 hr = CLSIDFromProgID(stdfont, &clsid);
392 ok(hr == S_OK, "got 0x%08x\n", hr);
393 clsid1 = CLSID_StdFont;
394 /* that's where it differs from StdFont */
395 clsid1.Data4[7] = 0x52;
396 ok(!IsEqualCLSID(&clsid, &CLSID_StdFont) && !IsEqualCLSID(&clsid, &CLSID_NULL) && !IsEqualCLSID(&clsid, &clsid1),
397 "got %s\n", wine_dbgstr_guid(&clsid));
399 pDeactivateActCtx(0, cookie);
400 pReleaseActCtx(handle);
404 static void test_CLSIDFromString(void)
406 CLSID clsid;
407 WCHAR wszCLSID_Broken[50];
408 UINT i;
410 HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
411 ok_ole_success(hr, "CLSIDFromString");
412 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
414 memset(&clsid, 0xab, sizeof(clsid));
415 hr = CLSIDFromString(NULL, &clsid);
416 ok(hr == S_OK, "got 0x%08x\n", hr);
417 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
419 /* string is longer, but starts with a valid CLSID */
420 memset(&clsid, 0, sizeof(clsid));
421 hr = CLSIDFromString(cf_brokenW, &clsid);
422 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
423 ok(IsEqualCLSID(&clsid, &IID_IClassFactory), "got %s\n", wine_dbgstr_guid(&clsid));
425 lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
426 for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
427 wszCLSID_Broken[i] = 'A';
428 wszCLSID_Broken[i] = '\0';
430 memset(&clsid, 0, sizeof(CLSID));
431 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
432 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
433 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
435 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
436 memset(&clsid, 0, sizeof(CLSID));
437 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
438 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
439 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
441 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
442 memset(&clsid, 0, sizeof(CLSID));
443 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
444 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
445 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
447 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
448 memset(&clsid, 0, sizeof(CLSID));
449 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
450 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
451 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
453 memset(&clsid, 0xcc, sizeof(CLSID));
454 hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
455 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
456 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
458 wszCLSID_Broken[9] = '*';
459 memset(&clsid, 0xcc, sizeof(CLSID));
460 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
461 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
462 ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
463 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
465 wszCLSID_Broken[3] = '*';
466 memset(&clsid, 0xcc, sizeof(CLSID));
467 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
468 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
469 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
470 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
472 wszCLSID_Broken[3] = '\0';
473 memset(&clsid, 0xcc, sizeof(CLSID));
474 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
475 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
476 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
477 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
480 static void test_IIDFromString(void)
482 static const WCHAR cfW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
483 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
484 static const WCHAR brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
485 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
486 static const WCHAR broken2W[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
487 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
488 static const WCHAR broken3W[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
489 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
490 HRESULT hr;
491 IID iid;
493 hr = IIDFromString(wszCLSID_StdFont, &iid);
494 ok(hr == S_OK, "got 0x%08x\n", hr);
495 ok(IsEqualIID(&iid, &CLSID_StdFont), "got iid %s\n", wine_dbgstr_guid(&iid));
497 memset(&iid, 0xab, sizeof(iid));
498 hr = IIDFromString(NULL, &iid);
499 ok(hr == S_OK, "got 0x%08x\n", hr);
500 ok(IsEqualIID(&iid, &CLSID_NULL), "got iid %s\n", wine_dbgstr_guid(&iid));
502 hr = IIDFromString(cfW, &iid);
503 ok(hr == S_OK, "got 0x%08x\n", hr);
504 ok(IsEqualIID(&iid, &IID_IClassFactory), "got iid %s\n", wine_dbgstr_guid(&iid));
506 /* string starts with a valid IID but is longer */
507 memset(&iid, 0xab, sizeof(iid));
508 hr = IIDFromString(cf_brokenW, &iid);
509 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
510 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
512 /* invalid IID in a valid format */
513 memset(&iid, 0xab, sizeof(iid));
514 hr = IIDFromString(brokenW, &iid);
515 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
516 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
518 memset(&iid, 0xab, sizeof(iid));
519 hr = IIDFromString(broken2W, &iid);
520 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
521 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
523 /* format is broken, but string length is okay */
524 memset(&iid, 0xab, sizeof(iid));
525 hr = IIDFromString(broken3W, &iid);
526 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
527 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
529 /* invalid string */
530 memset(&iid, 0xab, sizeof(iid));
531 hr = IIDFromString(wszNonExistent, &iid);
532 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
533 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
535 /* valid ProgID */
536 memset(&iid, 0xab, sizeof(iid));
537 hr = IIDFromString(stdfont, &iid);
538 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
539 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
542 static void test_StringFromGUID2(void)
544 WCHAR str[50];
545 int len;
547 /* invalid pointer */
548 SetLastError(0xdeadbeef);
549 len = StringFromGUID2(NULL,str,50);
550 ok(len == 0, "len: %d (expected 0)\n", len);
551 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
553 /* Test corner cases for buffer size */
554 len = StringFromGUID2(&CLSID_StdFont,str,50);
555 ok(len == 39, "len: %d (expected 39)\n", len);
556 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
558 memset(str,0,sizeof str);
559 len = StringFromGUID2(&CLSID_StdFont,str,39);
560 ok(len == 39, "len: %d (expected 39)\n", len);
561 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
563 len = StringFromGUID2(&CLSID_StdFont,str,38);
564 ok(len == 0, "len: %d (expected 0)\n", len);
566 len = StringFromGUID2(&CLSID_StdFont,str,30);
567 ok(len == 0, "len: %d (expected 0)\n", len);
570 struct info
572 HANDLE wait, stop;
575 static DWORD CALLBACK ole_initialize_thread(LPVOID pv)
577 HRESULT hr;
578 struct info *info = pv;
580 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
582 SetEvent(info->wait);
583 WaitForSingleObject(info->stop, 10000);
585 CoUninitialize();
586 return hr;
589 static void test_CoCreateInstance(void)
591 HRESULT hr;
592 HANDLE thread;
593 DWORD tid, exitcode;
594 IUnknown *pUnk;
595 struct info info;
596 REFCLSID rclsid = &CLSID_InternetZoneManager;
598 pUnk = (IUnknown *)0xdeadbeef;
599 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
600 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
601 ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
603 OleInitialize(NULL);
605 /* test errors returned for non-registered clsids */
606 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
607 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
608 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pUnk);
609 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
610 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (void **)&pUnk);
611 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
612 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_REMOTE_SERVER, &IID_IUnknown, (void **)&pUnk);
613 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
615 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
616 if(hr == REGDB_E_CLASSNOTREG)
618 skip("IE not installed so can't test CoCreateInstance\n");
619 OleUninitialize();
620 return;
623 ok_ole_success(hr, "CoCreateInstance");
624 if(pUnk) IUnknown_Release(pUnk);
625 OleUninitialize();
627 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
628 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
630 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
631 thread has already done so */
633 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
634 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
636 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
637 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
639 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
640 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
642 ok( !WaitForSingleObject(info.wait, 10000 ), "wait timed out\n" );
644 pUnk = (IUnknown *)0xdeadbeef;
645 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
646 ok(hr == S_OK, "CoCreateInstance should have returned S_OK instead of 0x%08x\n", hr);
647 if (pUnk) IUnknown_Release(pUnk);
649 SetEvent(info.stop);
650 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
652 GetExitCodeThread(thread, &exitcode);
653 hr = exitcode;
654 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
656 CloseHandle(thread);
657 CloseHandle(info.wait);
658 CloseHandle(info.stop);
661 static void test_CoGetClassObject(void)
663 HRESULT hr;
664 HANDLE thread, handle;
665 DWORD tid, exitcode;
666 ULONG_PTR cookie;
667 IUnknown *pUnk;
668 struct info info;
669 REFCLSID rclsid = &CLSID_InternetZoneManager;
670 HKEY hkey;
671 LONG res;
673 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
674 ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
675 ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
677 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
678 ok(hr == E_INVALIDARG ||
679 broken(hr == CO_E_NOTINITIALIZED), /* win9x */
680 "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
682 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
683 thread has already done so */
685 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
686 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
688 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
689 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
691 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
692 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
694 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
696 pUnk = (IUnknown *)0xdeadbeef;
697 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
698 if(hr == REGDB_E_CLASSNOTREG)
699 skip("IE not installed so can't test CoGetClassObject\n");
700 else
702 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
703 if (pUnk) IUnknown_Release(pUnk);
706 SetEvent(info.stop);
707 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
709 GetExitCodeThread(thread, &exitcode);
710 hr = exitcode;
711 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
713 CloseHandle(thread);
714 CloseHandle(info.wait);
715 CloseHandle(info.stop);
717 if (!pRegOverridePredefKey)
719 win_skip("RegOverridePredefKey not available\n");
720 return;
723 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
725 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
726 if (hr == S_OK)
728 IUnknown_Release(pUnk);
730 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
731 KEY_ALL_ACCESS, NULL, &hkey, NULL);
732 ok(!res, "RegCreateKeyEx returned %d\n", res);
734 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
735 ok(!res, "RegOverridePredefKey returned %d\n", res);
737 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
738 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
740 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
741 ok(!res, "RegOverridePredefKey returned %d\n", res);
743 if (hr == S_OK) IUnknown_Release(pUnk);
744 RegCloseKey(hkey);
747 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
748 ok(hr == S_OK, "got 0x%08x\n", hr);
749 IUnknown_Release(pUnk);
751 /* context redefines FreeMarshaler CLSID */
752 if ((handle = activate_context(actctx_manifest, &cookie)))
754 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
755 ok(hr == S_OK, "got 0x%08x\n", hr);
756 IUnknown_Release(pUnk);
758 pDeactivateActCtx(0, cookie);
759 pReleaseActCtx(handle);
762 CoUninitialize();
765 static ATOM register_dummy_class(void)
767 WNDCLASSA wc =
770 DefWindowProcA,
773 GetModuleHandleA(NULL),
774 NULL,
775 LoadCursorA(NULL, (LPSTR)IDC_ARROW),
776 (HBRUSH)(COLOR_BTNFACE+1),
777 NULL,
778 "WineOleTestClass",
781 return RegisterClassA(&wc);
784 static void test_ole_menu(void)
786 HWND hwndFrame;
787 HRESULT hr;
789 hwndFrame = CreateWindowA((LPCSTR)MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
790 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
791 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
793 DestroyWindow(hwndFrame);
797 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
799 if (ppvObj == NULL) return E_POINTER;
801 if (IsEqualGUID(riid, &IID_IUnknown) ||
802 IsEqualGUID(riid, &IID_IClassFactory))
804 *ppvObj = iface;
805 IMessageFilter_AddRef(iface);
806 return S_OK;
809 return E_NOINTERFACE;
812 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
814 return 2; /* non-heap object */
817 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
819 return 1; /* non-heap object */
822 static DWORD WINAPI MessageFilter_HandleInComingCall(
823 IMessageFilter *iface,
824 DWORD dwCallType,
825 HTASK threadIDCaller,
826 DWORD dwTickCount,
827 LPINTERFACEINFO lpInterfaceInfo)
829 trace("HandleInComingCall\n");
830 return SERVERCALL_ISHANDLED;
833 static DWORD WINAPI MessageFilter_RetryRejectedCall(
834 IMessageFilter *iface,
835 HTASK threadIDCallee,
836 DWORD dwTickCount,
837 DWORD dwRejectType)
839 trace("RetryRejectedCall\n");
840 return 0;
843 static DWORD WINAPI MessageFilter_MessagePending(
844 IMessageFilter *iface,
845 HTASK threadIDCallee,
846 DWORD dwTickCount,
847 DWORD dwPendingType)
849 trace("MessagePending\n");
850 return PENDINGMSG_WAITNOPROCESS;
853 static const IMessageFilterVtbl MessageFilter_Vtbl =
855 MessageFilter_QueryInterface,
856 MessageFilter_AddRef,
857 MessageFilter_Release,
858 MessageFilter_HandleInComingCall,
859 MessageFilter_RetryRejectedCall,
860 MessageFilter_MessagePending
863 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
865 static void test_CoRegisterMessageFilter(void)
867 HRESULT hr;
868 IMessageFilter *prev_filter;
870 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
871 ok(hr == CO_E_NOT_SUPPORTED,
872 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
873 hr);
875 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
876 prev_filter = (IMessageFilter *)0xdeadbeef;
877 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
878 ok(hr == CO_E_NOT_SUPPORTED,
879 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
880 hr);
881 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
882 "prev_filter should have been set to %p\n", prev_filter);
883 CoUninitialize();
885 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
887 hr = CoRegisterMessageFilter(NULL, NULL);
888 ok_ole_success(hr, "CoRegisterMessageFilter");
890 prev_filter = (IMessageFilter *)0xdeadbeef;
891 hr = CoRegisterMessageFilter(NULL, &prev_filter);
892 ok_ole_success(hr, "CoRegisterMessageFilter");
893 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
895 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
896 ok_ole_success(hr, "CoRegisterMessageFilter");
897 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
899 hr = CoRegisterMessageFilter(NULL, NULL);
900 ok_ole_success(hr, "CoRegisterMessageFilter");
902 CoUninitialize();
905 static HRESULT WINAPI Test_IUnknown_QueryInterface(
906 IUnknown *iface,
907 REFIID riid,
908 LPVOID *ppvObj)
910 if (ppvObj == NULL) return E_POINTER;
912 if (IsEqualIID(riid, &IID_IUnknown) ||
913 IsEqualIID(riid, &IID_IWineTest))
915 *ppvObj = iface;
916 IUnknown_AddRef(iface);
917 return S_OK;
920 *ppvObj = NULL;
921 return E_NOINTERFACE;
924 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
926 return 2; /* non-heap-based object */
929 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
931 return 1; /* non-heap-based object */
934 static const IUnknownVtbl TestUnknown_Vtbl =
936 Test_IUnknown_QueryInterface,
937 Test_IUnknown_AddRef,
938 Test_IUnknown_Release,
941 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
943 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
944 IPSFactoryBuffer * This,
945 /* [in] */ REFIID riid,
946 /* [iid_is][out] */ void **ppvObject)
948 if (IsEqualIID(riid, &IID_IUnknown) ||
949 IsEqualIID(riid, &IID_IPSFactoryBuffer))
951 *ppvObject = This;
952 IPSFactoryBuffer_AddRef(This);
953 return S_OK;
955 return E_NOINTERFACE;
958 static ULONG WINAPI PSFactoryBuffer_AddRef(
959 IPSFactoryBuffer * This)
961 return 2;
964 static ULONG WINAPI PSFactoryBuffer_Release(
965 IPSFactoryBuffer * This)
967 return 1;
970 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
971 IPSFactoryBuffer * This,
972 /* [in] */ IUnknown *pUnkOuter,
973 /* [in] */ REFIID riid,
974 /* [out] */ IRpcProxyBuffer **ppProxy,
975 /* [out] */ void **ppv)
977 return E_NOTIMPL;
980 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
981 IPSFactoryBuffer * This,
982 /* [in] */ REFIID riid,
983 /* [unique][in] */ IUnknown *pUnkServer,
984 /* [out] */ IRpcStubBuffer **ppStub)
986 return E_NOTIMPL;
989 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
991 PSFactoryBuffer_QueryInterface,
992 PSFactoryBuffer_AddRef,
993 PSFactoryBuffer_Release,
994 PSFactoryBuffer_CreateProxy,
995 PSFactoryBuffer_CreateStub
998 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
1000 static const CLSID CLSID_WineTestPSFactoryBuffer =
1002 0x52011640,
1003 0x8164,
1004 0x4fd0,
1005 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1006 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
1008 static void test_CoRegisterPSClsid(void)
1010 HRESULT hr;
1011 DWORD dwRegistrationKey;
1012 IStream *stream;
1013 CLSID clsid;
1015 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1016 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1018 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1020 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
1021 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
1022 ok_ole_success(hr, "CoRegisterClassObject");
1024 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1025 ok_ole_success(hr, "CoRegisterPSClsid");
1027 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1028 ok_ole_success(hr, "CreateStreamOnHGlobal");
1030 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1031 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1032 IStream_Release(stream);
1034 hr = CoRevokeClassObject(dwRegistrationKey);
1035 ok_ole_success(hr, "CoRevokeClassObject");
1037 CoUninitialize();
1039 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1041 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1042 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
1044 CoUninitialize();
1047 static void test_CoGetPSClsid(void)
1049 ULONG_PTR cookie;
1050 HANDLE handle;
1051 HRESULT hr;
1052 CLSID clsid;
1053 HKEY hkey;
1054 LONG res;
1055 const BOOL is_win64 = (sizeof(void*) != sizeof(int));
1056 BOOL is_wow64 = FALSE;
1058 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1059 ok(hr == CO_E_NOTINITIALIZED,
1060 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
1061 hr);
1063 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1065 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1066 ok_ole_success(hr, "CoGetPSClsid");
1068 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1069 ok(hr == REGDB_E_IIDNOTREG,
1070 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
1071 hr);
1073 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
1074 ok(hr == E_INVALIDARG,
1075 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
1076 hr);
1078 if (!pRegOverridePredefKey)
1080 win_skip("RegOverridePredefKey not available\n");
1081 CoUninitialize();
1082 return;
1084 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1085 ok_ole_success(hr, "CoGetPSClsid");
1087 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
1088 KEY_ALL_ACCESS, NULL, &hkey, NULL);
1089 ok(!res, "RegCreateKeyEx returned %d\n", res);
1091 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
1092 ok(!res, "RegOverridePredefKey returned %d\n", res);
1094 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1095 ok_ole_success(hr, "CoGetPSClsid");
1097 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
1098 ok(!res, "RegOverridePredefKey returned %d\n", res);
1100 RegCloseKey(hkey);
1102 /* not registered CLSID */
1103 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1104 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1106 if ((handle = activate_context(actctx_manifest, &cookie)))
1108 memset(&clsid, 0, sizeof(clsid));
1109 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1110 ok(hr == S_OK, "got 0x%08x\n", hr);
1111 ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1113 memset(&clsid, 0, sizeof(clsid));
1114 hr = CoGetPSClsid(&IID_Testiface2, &clsid);
1115 ok(hr == S_OK, "got 0x%08x\n", hr);
1116 ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1118 memset(&clsid, 0, sizeof(clsid));
1119 hr = CoGetPSClsid(&IID_Testiface3, &clsid);
1120 ok(hr == S_OK, "got 0x%08x\n", hr);
1121 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1123 memset(&clsid, 0xaa, sizeof(clsid));
1124 hr = CoGetPSClsid(&IID_Testiface4, &clsid);
1125 ok(hr == S_OK, "got 0x%08x\n", hr);
1126 ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1128 /* register same interface and try to get CLSID back */
1129 hr = CoRegisterPSClsid(&IID_Testiface, &IID_Testiface4);
1130 ok(hr == S_OK, "got 0x%08x\n", hr);
1131 memset(&clsid, 0, sizeof(clsid));
1132 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1133 ok(hr == S_OK, "got 0x%08x\n", hr);
1134 ok(IsEqualGUID(&clsid, &IID_Testiface4), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1136 pDeactivateActCtx(0, cookie);
1137 pReleaseActCtx(handle);
1140 if (pRegDeleteKeyExA &&
1141 (is_win64 ||
1142 (pIsWow64Process && pIsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
1144 static GUID IID_DeadBeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1145 static const char clsidDeadBeef[] = "{deadbeef-dead-beef-dead-beefdeadbeef}";
1146 static const char clsidA[] = "{66666666-8888-7777-6666-555555555555}";
1147 HKEY hkey_iface, hkey_psclsid;
1148 REGSAM opposite = is_win64 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
1150 hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1151 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1153 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, "Interface",
1154 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_iface, NULL);
1155 ok(!res, "RegCreateKeyEx returned %d\n", res);
1156 res = RegCreateKeyExA(hkey_iface, clsidDeadBeef,
1157 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey, NULL);
1158 ok(!res, "RegCreateKeyEx returned %d\n", res);
1159 res = RegCreateKeyExA(hkey, "ProxyStubClsid32",
1160 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_psclsid, NULL);
1161 res = RegSetValueExA(hkey_psclsid, NULL, 0, REG_SZ, (const BYTE *)clsidA, strlen(clsidA)+1);
1162 ok(!res, "RegSetValueEx returned %d\n", res);
1163 RegCloseKey(hkey_psclsid);
1165 hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1166 ok_ole_success(hr, "CoGetPSClsid");
1167 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1169 res = pRegDeleteKeyExA(hkey, "ProxyStubClsid32", opposite, 0);
1170 ok(!res, "RegDeleteKeyEx returned %d\n", res);
1171 RegCloseKey(hkey);
1172 res = pRegDeleteKeyExA(hkey_iface, clsidDeadBeef, opposite, 0);
1173 ok(!res, "RegDeleteKeyEx returned %d\n", res);
1174 RegCloseKey(hkey_iface);
1177 CoUninitialize();
1180 /* basic test, mainly for invalid arguments. see marshal.c for more */
1181 static void test_CoUnmarshalInterface(void)
1183 IUnknown *pProxy;
1184 IStream *pStream;
1185 HRESULT hr;
1187 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
1188 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1190 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1191 ok_ole_success(hr, "CreateStreamOnHGlobal");
1193 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1194 todo_wine
1195 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1197 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1199 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1200 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1202 CoUninitialize();
1204 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
1205 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1207 IStream_Release(pStream);
1210 static void test_CoGetInterfaceAndReleaseStream(void)
1212 HRESULT hr;
1213 IUnknown *pUnk;
1215 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1217 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
1218 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
1220 CoUninitialize();
1223 /* basic test, mainly for invalid arguments. see marshal.c for more */
1224 static void test_CoMarshalInterface(void)
1226 IStream *pStream;
1227 HRESULT hr;
1228 static const LARGE_INTEGER llZero;
1230 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1232 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1233 ok_ole_success(hr, "CreateStreamOnHGlobal");
1235 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1236 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1238 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1239 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1241 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1242 ok_ole_success(hr, "CoMarshalInterface");
1244 /* stream not rewound */
1245 hr = CoReleaseMarshalData(pStream);
1246 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1248 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1249 ok_ole_success(hr, "IStream_Seek");
1251 hr = CoReleaseMarshalData(pStream);
1252 ok_ole_success(hr, "CoReleaseMarshalData");
1254 IStream_Release(pStream);
1256 CoUninitialize();
1259 static void test_CoMarshalInterThreadInterfaceInStream(void)
1261 IStream *pStream;
1262 HRESULT hr;
1263 IClassFactory *pProxy;
1265 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1267 cLocks = 0;
1269 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
1270 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1272 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
1273 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1275 ok_no_locks();
1277 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
1278 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
1280 ok_more_than_one_lock();
1282 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1283 ok_ole_success(hr, "CoUnmarshalInterface");
1285 IClassFactory_Release(pProxy);
1286 IStream_Release(pStream);
1288 ok_no_locks();
1290 CoUninitialize();
1293 static void test_CoRegisterClassObject(void)
1295 ULONG_PTR ctxcookie;
1296 HANDLE handle;
1297 DWORD cookie;
1298 HRESULT hr;
1299 IClassFactory *pcf;
1301 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1303 /* CLSCTX_INPROC_SERVER */
1304 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1305 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1306 ok_ole_success(hr, "CoRegisterClassObject");
1307 hr = CoRevokeClassObject(cookie);
1308 ok_ole_success(hr, "CoRevokeClassObject");
1310 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1311 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1312 ok_ole_success(hr, "CoRegisterClassObject");
1313 hr = CoRevokeClassObject(cookie);
1314 ok_ole_success(hr, "CoRevokeClassObject");
1316 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1317 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1318 ok_ole_success(hr, "CoRegisterClassObject");
1319 hr = CoRevokeClassObject(cookie);
1320 ok_ole_success(hr, "CoRevokeClassObject");
1322 /* CLSCTX_LOCAL_SERVER */
1323 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1324 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1325 ok_ole_success(hr, "CoRegisterClassObject");
1326 hr = CoRevokeClassObject(cookie);
1327 ok_ole_success(hr, "CoRevokeClassObject");
1329 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1330 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1331 ok_ole_success(hr, "CoRegisterClassObject");
1332 hr = CoRevokeClassObject(cookie);
1333 ok_ole_success(hr, "CoRevokeClassObject");
1335 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1336 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1337 ok_ole_success(hr, "CoRegisterClassObject");
1338 hr = CoRevokeClassObject(cookie);
1339 ok_ole_success(hr, "CoRevokeClassObject");
1341 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
1342 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1343 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1344 ok_ole_success(hr, "CoRegisterClassObject");
1345 hr = CoRevokeClassObject(cookie);
1346 ok_ole_success(hr, "CoRevokeClassObject");
1348 /* test whether an object that doesn't support IClassFactory can be
1349 * registered for CLSCTX_LOCAL_SERVER */
1350 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
1351 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1352 ok_ole_success(hr, "CoRegisterClassObject");
1353 hr = CoRevokeClassObject(cookie);
1354 ok_ole_success(hr, "CoRevokeClassObject");
1356 /* test whether registered class becomes invalid when apartment is destroyed */
1357 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1358 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1359 ok_ole_success(hr, "CoRegisterClassObject");
1361 CoUninitialize();
1362 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1364 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
1365 &IID_IClassFactory, (void **)&pcf);
1366 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
1368 /* crashes with at least win9x DCOM! */
1369 if (0)
1370 CoRevokeClassObject(cookie);
1372 /* test that object is accessible */
1373 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER,
1374 REGCLS_MULTIPLEUSE, &cookie);
1375 ok(hr == S_OK, "got 0x%08x\n", hr);
1377 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1378 ok(hr == S_OK, "got 0x%08x\n", hr);
1379 IClassFactory_Release(pcf);
1381 /* context now contains CLSID_WineOOPTest, test if registered one could still be used */
1382 if ((handle = activate_context(actctx_manifest, &ctxcookie)))
1384 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1385 todo_wine
1386 ok(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), "got 0x%08x\n", hr);
1388 pDeactivateActCtx(0, ctxcookie);
1389 pReleaseActCtx(handle);
1392 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1393 ok(hr == S_OK, "got 0x%08x\n", hr);
1394 IClassFactory_Release(pcf);
1396 hr = CoRevokeClassObject(cookie);
1397 ok(hr == S_OK, "got 0x%08x\n", hr);
1399 CoUninitialize();
1402 static HRESULT get_class_object(CLSCTX clsctx)
1404 HRESULT hr;
1405 IClassFactory *pcf;
1407 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1408 (void **)&pcf);
1410 if (SUCCEEDED(hr))
1411 IClassFactory_Release(pcf);
1413 return hr;
1416 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1418 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1419 HRESULT hr;
1421 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1423 hr = get_class_object(clsctx);
1425 CoUninitialize();
1427 return hr;
1430 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1432 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1433 HRESULT hr;
1434 IClassFactory *pcf;
1435 IMultiQI *pMQI;
1437 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1439 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1440 (void **)&pcf);
1442 if (SUCCEEDED(hr))
1444 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1445 if (SUCCEEDED(hr))
1446 IMultiQI_Release(pMQI);
1447 IClassFactory_Release(pcf);
1450 CoUninitialize();
1452 return hr;
1455 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1457 HRESULT hr;
1458 DWORD cookie;
1460 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1462 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1463 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1465 CoUninitialize();
1467 return hr;
1470 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1472 DWORD cookie = (DWORD_PTR)pv;
1473 HRESULT hr;
1475 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1477 hr = CoRevokeClassObject(cookie);
1479 CoUninitialize();
1481 return hr;
1484 static void test_registered_object_thread_affinity(void)
1486 HRESULT hr;
1487 DWORD cookie;
1488 HANDLE thread;
1489 DWORD tid;
1490 DWORD exitcode;
1492 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1494 /* CLSCTX_INPROC_SERVER */
1496 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1497 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1498 ok_ole_success(hr, "CoRegisterClassObject");
1500 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1501 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1502 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1503 GetExitCodeThread(thread, &exitcode);
1504 hr = exitcode;
1505 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1506 "registered in different thread should return REGDB_E_CLASSNOTREG "
1507 "instead of 0x%08x\n", hr);
1509 hr = get_class_object(CLSCTX_INPROC_SERVER);
1510 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1511 "thread should return S_OK instead of 0x%08x\n", hr);
1513 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1514 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1515 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1516 GetExitCodeThread(thread, &exitcode);
1517 hr = exitcode;
1518 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1520 hr = CoRevokeClassObject(cookie);
1521 ok_ole_success(hr, "CoRevokeClassObject");
1523 /* CLSCTX_LOCAL_SERVER */
1525 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1526 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1527 ok_ole_success(hr, "CoRegisterClassObject");
1529 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1530 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1531 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1533 MSG msg;
1534 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1536 TranslateMessage(&msg);
1537 DispatchMessageA(&msg);
1540 GetExitCodeThread(thread, &exitcode);
1541 hr = exitcode;
1542 ok(hr == S_OK, "CoGetClassObject on local server object "
1543 "registered in different thread should return S_OK "
1544 "instead of 0x%08x\n", hr);
1546 hr = get_class_object(CLSCTX_LOCAL_SERVER);
1547 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1548 "thread should return S_OK instead of 0x%08x\n", hr);
1550 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid);
1551 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1552 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1553 GetExitCodeThread(thread, &exitcode);
1554 hr = exitcode;
1555 ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different "
1556 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1558 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1559 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1560 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1561 GetExitCodeThread(thread, &exitcode);
1562 hr = exitcode;
1563 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1564 "thread should return S_OK instead of 0x%08x\n", hr);
1566 hr = CoRevokeClassObject(cookie);
1567 ok_ole_success(hr, "CoRevokeClassObject");
1569 CoUninitialize();
1572 static DWORD CALLBACK free_libraries_thread(LPVOID p)
1574 CoFreeUnusedLibraries();
1575 return 0;
1578 static inline BOOL is_module_loaded(const char *module)
1580 return GetModuleHandleA(module) != 0;
1583 static void test_CoFreeUnusedLibraries(void)
1585 HRESULT hr;
1586 IUnknown *pUnk;
1587 DWORD tid;
1588 HANDLE thread;
1590 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1592 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1594 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1595 if (hr == REGDB_E_CLASSNOTREG)
1597 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1598 CoUninitialize();
1599 return;
1601 ok_ole_success(hr, "CoCreateInstance");
1603 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1605 ok(pUnk != NULL ||
1606 broken(pUnk == NULL), /* win9x */
1607 "Expected a valid pointer\n");
1608 if (pUnk)
1609 IUnknown_Release(pUnk);
1611 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1613 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1614 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1615 CloseHandle(thread);
1617 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1619 CoFreeUnusedLibraries();
1621 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1623 CoUninitialize();
1626 static void test_CoGetObjectContext(void)
1628 HRESULT hr;
1629 ULONG refs;
1630 IComThreadingInfo *pComThreadingInfo;
1631 IContextCallback *pContextCallback;
1632 IObjContext *pObjContext;
1633 APTTYPE apttype;
1634 THDTYPE thdtype;
1635 struct info info;
1636 HANDLE thread;
1637 DWORD tid, exitcode;
1639 if (!pCoGetObjectContext)
1641 skip("CoGetObjectContext not present\n");
1642 return;
1645 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1646 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1647 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1649 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1650 thread has already done so */
1652 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
1653 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1655 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
1656 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1658 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1659 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1661 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1663 pComThreadingInfo = NULL;
1664 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1665 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1666 IComThreadingInfo_Release(pComThreadingInfo);
1668 SetEvent(info.stop);
1669 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1671 GetExitCodeThread(thread, &exitcode);
1672 hr = exitcode;
1673 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1675 CloseHandle(thread);
1676 CloseHandle(info.wait);
1677 CloseHandle(info.stop);
1679 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1681 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1682 ok_ole_success(hr, "CoGetObjectContext");
1684 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1685 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1686 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1688 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1689 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1690 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1692 refs = IComThreadingInfo_Release(pComThreadingInfo);
1693 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1695 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1696 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1698 if (hr == S_OK)
1700 refs = IContextCallback_Release(pContextCallback);
1701 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1704 CoUninitialize();
1706 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1708 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1709 ok_ole_success(hr, "CoGetObjectContext");
1711 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1712 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1713 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1715 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1716 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1717 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1719 refs = IComThreadingInfo_Release(pComThreadingInfo);
1720 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1722 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1723 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1725 if (hr == S_OK)
1727 refs = IContextCallback_Release(pContextCallback);
1728 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1731 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1732 ok_ole_success(hr, "CoGetObjectContext");
1734 refs = IObjContext_Release(pObjContext);
1735 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
1737 CoUninitialize();
1740 typedef struct {
1741 IUnknown IUnknown_iface;
1742 LONG refs;
1743 } Test_CallContext;
1745 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
1747 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
1750 static HRESULT WINAPI Test_CallContext_QueryInterface(
1751 IUnknown *iface,
1752 REFIID riid,
1753 LPVOID *ppvObj)
1755 if (ppvObj == NULL) return E_POINTER;
1757 if (IsEqualGUID(riid, &IID_IUnknown))
1759 *ppvObj = iface;
1760 IUnknown_AddRef(iface);
1761 return S_OK;
1764 *ppvObj = NULL;
1765 return E_NOINTERFACE;
1768 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
1770 Test_CallContext *This = impl_from_IUnknown(iface);
1771 return InterlockedIncrement(&This->refs);
1774 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
1776 Test_CallContext *This = impl_from_IUnknown(iface);
1777 ULONG refs = InterlockedDecrement(&This->refs);
1778 if (!refs)
1779 HeapFree(GetProcessHeap(), 0, This);
1780 return refs;
1783 static const IUnknownVtbl TestCallContext_Vtbl =
1785 Test_CallContext_QueryInterface,
1786 Test_CallContext_AddRef,
1787 Test_CallContext_Release
1790 static void test_CoGetCallContext(void)
1792 HRESULT hr;
1793 ULONG refs;
1794 IUnknown *pUnk;
1795 Test_CallContext *test_object;
1797 if (!pCoSwitchCallContext)
1799 skip("CoSwitchCallContext not present\n");
1800 return;
1803 CoInitialize(NULL);
1805 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
1806 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
1807 test_object->refs = 1;
1809 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1810 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1812 pUnk = (IUnknown*)0xdeadbeef;
1813 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
1814 ok_ole_success(hr, "CoSwitchCallContext");
1815 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
1816 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1817 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1818 IUnknown_Release(&test_object->IUnknown_iface);
1820 pUnk = (IUnknown*)0xdeadbeef;
1821 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1822 ok_ole_success(hr, "CoGetCallContext");
1823 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1824 &test_object->IUnknown_iface, pUnk);
1825 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1826 ok(refs == 3, "Expected refcount 3, got %d\n", refs);
1827 IUnknown_Release(&test_object->IUnknown_iface);
1828 IUnknown_Release(pUnk);
1830 pUnk = (IUnknown*)0xdeadbeef;
1831 hr = pCoSwitchCallContext(NULL, &pUnk);
1832 ok_ole_success(hr, "CoSwitchCallContext");
1833 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1834 &test_object->IUnknown_iface, pUnk);
1835 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1836 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1837 IUnknown_Release(&test_object->IUnknown_iface);
1839 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1840 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1842 IUnknown_Release(&test_object->IUnknown_iface);
1844 CoUninitialize();
1847 static void test_CoGetContextToken(void)
1849 HRESULT hr;
1850 ULONG refs;
1851 ULONG_PTR token;
1852 IObjContext *ctx;
1853 struct info info;
1854 HANDLE thread;
1855 DWORD tid, exitcode;
1857 if (!pCoGetContextToken)
1859 win_skip("CoGetContextToken not present\n");
1860 return;
1863 token = 0xdeadbeef;
1864 hr = pCoGetContextToken(&token);
1865 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
1866 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
1868 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1869 thread has already done so */
1871 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
1872 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1874 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
1875 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1877 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1878 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1880 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1882 token = 0;
1883 hr = pCoGetContextToken(&token);
1884 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1886 SetEvent(info.stop);
1887 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1889 GetExitCodeThread(thread, &exitcode);
1890 hr = exitcode;
1891 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1893 CloseHandle(thread);
1894 CloseHandle(info.wait);
1895 CloseHandle(info.stop);
1897 CoInitialize(NULL);
1899 hr = pCoGetContextToken(NULL);
1900 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
1902 token = 0;
1903 hr = pCoGetContextToken(&token);
1904 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1905 ok(token, "Expected token != 0\n");
1907 refs = IUnknown_AddRef((IUnknown *)token);
1908 todo_wine ok(refs == 1, "Expected 1, got %u\n", refs);
1910 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
1911 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1912 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1914 refs = IObjContext_AddRef(ctx);
1915 todo_wine ok(refs == 3, "Expected 3, got %u\n", refs);
1917 refs = IObjContext_Release(ctx);
1918 todo_wine ok(refs == 2, "Expected 2, got %u\n", refs);
1920 refs = IUnknown_Release((IUnknown *)token);
1921 ok(refs == 1, "Expected 1, got %u\n", refs);
1923 /* CoGetContextToken does not add a reference */
1924 token = 0;
1925 hr = pCoGetContextToken(&token);
1926 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1927 ok(token, "Expected token != 0\n");
1928 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1930 refs = IObjContext_AddRef(ctx);
1931 ok(refs == 2, "Expected 1, got %u\n", refs);
1933 refs = IObjContext_Release(ctx);
1934 ok(refs == 1, "Expected 0, got %u\n", refs);
1936 refs = IObjContext_Release(ctx);
1937 ok(refs == 0, "Expected 0, got %u\n", refs);
1939 CoUninitialize();
1942 static void test_TreatAsClass(void)
1944 HRESULT hr;
1945 CLSID out;
1946 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1947 static const char deadbeefA[] = "{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}";
1948 IInternetProtocol *pIP = NULL;
1949 HKEY clsidkey, deadbeefkey;
1950 LONG lr;
1952 if (!pCoGetTreatAsClass)
1954 win_skip("CoGetTreatAsClass not present\n");
1955 return;
1957 hr = pCoGetTreatAsClass(&deadbeef,&out);
1958 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
1959 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
1961 lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &clsidkey);
1962 ok(lr == ERROR_SUCCESS, "Couldn't open CLSID key\n");
1964 lr = RegCreateKeyExA(clsidkey, deadbeefA, 0, NULL, 0, KEY_WRITE, NULL, &deadbeefkey, NULL);
1965 ok(lr == ERROR_SUCCESS, "Couldn't create class key\n");
1967 hr = pCoTreatAsClass(&deadbeef, &deadbeef);
1968 ok(hr == REGDB_E_WRITEREGDB, "CoTreatAsClass gave wrong error: %08x\n", hr);
1970 hr = pCoTreatAsClass(&deadbeef, &CLSID_FileProtocol);
1971 if(hr == REGDB_E_WRITEREGDB){
1972 win_skip("Insufficient privileges to use CoTreatAsClass\n");
1973 goto exit;
1975 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
1977 hr = pCoGetTreatAsClass(&deadbeef, &out);
1978 ok(hr == S_OK, "CoGetTreatAsClass failed: %08x\n",hr);
1979 ok(IsEqualGUID(&out, &CLSID_FileProtocol), "expected to get substituted clsid\n");
1981 OleInitialize(NULL);
1983 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
1984 if(hr == REGDB_E_CLASSNOTREG)
1986 win_skip("IE not installed so can't test CoCreateInstance\n");
1987 goto exit;
1990 ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
1991 if(pIP){
1992 IInternetProtocol_Release(pIP);
1993 pIP = NULL;
1996 hr = pCoTreatAsClass(&deadbeef, &CLSID_NULL);
1997 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
1999 hr = pCoGetTreatAsClass(&deadbeef, &out);
2000 ok(hr == S_FALSE, "expected S_FALSE got %08x\n", hr);
2001 ok(IsEqualGUID(&out, &deadbeef), "expected to get same clsid back\n");
2003 /* bizarrely, native's CoTreatAsClass takes some time to take effect in CoCreateInstance */
2004 Sleep(200);
2006 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2007 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance gave wrong error: %08x\n", hr);
2009 if(pIP)
2010 IInternetProtocol_Release(pIP);
2012 exit:
2013 OleUninitialize();
2014 RegCloseKey(deadbeefkey);
2015 RegDeleteKeyA(clsidkey, deadbeefA);
2016 RegCloseKey(clsidkey);
2019 static void test_CoInitializeEx(void)
2021 HRESULT hr;
2023 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2024 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2026 /* Calling OleInitialize for the first time should yield S_OK even with
2027 * apartment already initialized by previous CoInitialize(Ex) calls. */
2028 hr = OleInitialize(NULL);
2029 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
2031 /* Subsequent calls to OleInitialize should return S_FALSE */
2032 hr = OleInitialize(NULL);
2033 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
2035 /* Cleanup */
2036 CoUninitialize();
2037 OleUninitialize();
2038 OleUninitialize();
2041 static void test_OleRegGetMiscStatus(void)
2043 ULONG_PTR cookie;
2044 HANDLE handle;
2045 DWORD status;
2046 HRESULT hr;
2048 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, NULL);
2049 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2051 status = 0xdeadbeef;
2052 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2053 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
2054 ok(status == 0, "got 0x%08x\n", status);
2056 status = -1;
2057 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2058 ok(hr == S_OK, "got 0x%08x\n", hr);
2059 ok(status == 0, "got 0x%08x\n", status);
2061 if ((handle = activate_context(actctx_manifest, &cookie)))
2063 status = 0;
2064 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2065 ok(hr == S_OK, "got 0x%08x\n", hr);
2066 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2068 /* context data takes precedence over registration info */
2069 status = 0;
2070 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2071 ok(hr == S_OK, "got 0x%08x\n", hr);
2072 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2074 /* there's no such attribute in context */
2075 status = -1;
2076 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status);
2077 ok(hr == S_OK, "got 0x%08x\n", hr);
2078 ok(status == 0, "got 0x%08x\n", status);
2080 pDeactivateActCtx(0, cookie);
2081 pReleaseActCtx(handle);
2085 static void test_CoCreateGuid(void)
2087 HRESULT hr;
2089 hr = CoCreateGuid(NULL);
2090 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2093 static void CALLBACK apc_test_proc(ULONG_PTR param)
2095 /* nothing */
2098 static DWORD CALLBACK release_semaphore_thread( LPVOID arg )
2100 HANDLE handle = arg;
2101 if (WaitForSingleObject(handle, 200) == WAIT_TIMEOUT)
2102 ReleaseSemaphore(handle, 1, NULL);
2103 return 0;
2106 static void test_CoWaitForMultipleHandles(void)
2108 static const char cls_name[] = "cowait_test_class";
2109 HANDLE handles[2], thread;
2110 DWORD index, tid;
2111 WNDCLASSEXA wc;
2112 BOOL success;
2113 HRESULT hr;
2114 HWND hWnd;
2115 MSG msg;
2117 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2118 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2120 memset(&wc, 0, sizeof(wc));
2121 wc.cbSize = sizeof(wc);
2122 wc.style = CS_VREDRAW | CS_HREDRAW;
2123 wc.hInstance = GetModuleHandleA(0);
2124 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2125 wc.hbrBackground = NULL;
2126 wc.lpszClassName = cls_name;
2127 wc.lpfnWndProc = DefWindowProcA;
2128 success = RegisterClassExA(&wc) != 0;
2129 ok(success, "RegisterClassExA failed %u\n", GetLastError());
2131 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2132 ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
2133 handles[0] = CreateSemaphoreA(NULL, 1, 1, NULL);
2134 ok(handles[0] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2135 handles[1] = CreateSemaphoreA(NULL, 1, 1, NULL);
2136 ok(handles[1] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2138 /* test without flags */
2140 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2141 hr = CoWaitForMultipleHandles(0, 50, 0, handles, NULL);
2142 todo_wine
2143 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2144 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2145 todo_wine
2146 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2148 index = 0xdeadbeef;
2149 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2150 hr = CoWaitForMultipleHandles(0, 50, 0, NULL, &index);
2151 todo_wine
2152 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2153 todo_wine
2154 ok(index == 0, "expected index 0, got %u\n", index);
2155 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2156 todo_wine
2157 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2159 index = 0xdeadbeef;
2160 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2161 hr = CoWaitForMultipleHandles(0, 50, 0, handles, &index);
2162 todo_wine
2163 ok(hr == RPC_E_NO_SYNC, "expected RPC_E_NO_SYNC, got 0x%08x\n", hr);
2164 todo_wine
2165 ok(index == 0, "expected index 0, got %u\n", index);
2166 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2167 todo_wine
2168 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2170 index = 0xdeadbeef;
2171 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2172 hr = CoWaitForMultipleHandles(0, 50, 1, handles, &index);
2173 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2174 ok(index == 0, "expected index 0, got %u\n", index);
2175 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2176 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2178 index = 0xdeadbeef;
2179 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2180 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2181 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2182 ok(index == 1, "expected index 1, got %u\n", index);
2183 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2184 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2186 index = 0xdeadbeef;
2187 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2188 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2189 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2190 todo_wine
2191 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2192 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2193 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2195 ReleaseSemaphore(handles[0], 1, NULL);
2196 ReleaseSemaphore(handles[1], 1, NULL);
2198 /* test with COWAIT_WAITALL */
2200 index = 0xdeadbeef;
2201 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2202 hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 50, 2, handles, &index);
2203 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2204 ok(index == 0, "expected index 0, got %u\n", index);
2205 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2206 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2208 index = 0xdeadbeef;
2209 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2210 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2211 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2212 todo_wine
2213 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2214 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2215 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2217 ReleaseSemaphore(handles[0], 1, NULL);
2218 ReleaseSemaphore(handles[1], 1, NULL);
2220 /* test with COWAIT_ALERTABLE */
2222 index = 0xdeadbeef;
2223 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2224 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 1, handles, &index);
2225 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2226 ok(index == 0, "expected index 0, got %u\n", index);
2227 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2228 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2230 index = 0xdeadbeef;
2231 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2232 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2233 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2234 ok(index == 1, "expected index 1, got %u\n", index);
2235 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2236 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2238 index = 0xdeadbeef;
2239 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2240 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2241 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2242 todo_wine
2243 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2244 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2245 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2247 index = 0xdeadbeef;
2248 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2249 success = QueueUserAPC(apc_test_proc, GetCurrentThread(), 0);
2250 ok(success, "QueueUserAPC failed %u\n", GetLastError());
2251 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2252 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2253 ok(index == WAIT_IO_COMPLETION, "expected index WAIT_IO_COMPLETION, got %u\n", index);
2254 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2255 todo_wine
2256 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2258 /* test with COWAIT_INPUTAVAILABLE (semaphores are still locked) */
2260 index = 0xdeadbeef;
2261 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2262 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2263 ok(success, "PeekMessageA returned FALSE\n");
2264 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2265 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2266 todo_wine
2267 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2268 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2269 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2271 index = 0xdeadbeef;
2272 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2273 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2274 ok(success, "PeekMessageA returned FALSE\n");
2275 thread = CreateThread(NULL, 0, release_semaphore_thread, handles[1], 0, &tid);
2276 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2277 hr = CoWaitForMultipleHandles(COWAIT_INPUTAVAILABLE, 50, 2, handles, &index);
2278 ok(hr == RPC_S_CALLPENDING || broken(hr == E_INVALIDARG) || broken(hr == S_OK) /* Win 8 */,
2279 "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2280 ReleaseSemaphore(handles[1], 1, NULL);
2281 todo_wine
2282 ok(index == 0 || broken(index == 1) /* Win 8 */, "expected index 0, got %u\n", index);
2283 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2284 ok(!success || broken(success && hr == E_INVALIDARG),
2285 "CoWaitForMultipleHandles didn't pump any messages\n");
2286 index = WaitForSingleObject(thread, 200);
2287 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2288 CloseHandle(thread);
2290 CloseHandle(handles[0]);
2291 CloseHandle(handles[1]);
2292 DestroyWindow(hWnd);
2294 success = UnregisterClassA(cls_name, GetModuleHandleA(0));
2295 ok(success, "UnregisterClass failed %u\n", GetLastError());
2297 CoUninitialize();
2300 static void init_funcs(void)
2302 HMODULE hOle32 = GetModuleHandleA("ole32");
2303 HMODULE hAdvapi32 = GetModuleHandleA("advapi32");
2304 HMODULE hkernel32 = GetModuleHandleA("kernel32");
2306 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
2307 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
2308 pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
2309 pCoTreatAsClass = (void*)GetProcAddress(hOle32,"CoTreatAsClass");
2310 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
2311 pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA");
2312 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
2313 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
2315 pActivateActCtx = (void*)GetProcAddress(hkernel32, "ActivateActCtx");
2316 pCreateActCtxW = (void*)GetProcAddress(hkernel32, "CreateActCtxW");
2317 pDeactivateActCtx = (void*)GetProcAddress(hkernel32, "DeactivateActCtx");
2318 pIsWow64Process = (void*)GetProcAddress(hkernel32, "IsWow64Process");
2319 pReleaseActCtx = (void*)GetProcAddress(hkernel32, "ReleaseActCtx");
2322 START_TEST(compobj)
2324 init_funcs();
2326 if (!pCoInitializeEx)
2328 trace("You need DCOM95 installed to run this test\n");
2329 return;
2332 if (!pCreateActCtxW)
2333 win_skip("Activation contexts are not supported, some tests will be skipped.\n");
2335 test_ProgIDFromCLSID();
2336 test_CLSIDFromProgID();
2337 test_CLSIDFromString();
2338 test_IIDFromString();
2339 test_StringFromGUID2();
2340 test_CoCreateInstance();
2341 test_ole_menu();
2342 test_CoGetClassObject();
2343 test_CoRegisterMessageFilter();
2344 test_CoRegisterPSClsid();
2345 test_CoGetPSClsid();
2346 test_CoUnmarshalInterface();
2347 test_CoGetInterfaceAndReleaseStream();
2348 test_CoMarshalInterface();
2349 test_CoMarshalInterThreadInterfaceInStream();
2350 test_CoRegisterClassObject();
2351 test_registered_object_thread_affinity();
2352 test_CoFreeUnusedLibraries();
2353 test_CoGetObjectContext();
2354 test_CoGetCallContext();
2355 test_CoGetContextToken();
2356 test_TreatAsClass();
2357 test_CoInitializeEx();
2358 test_OleRegGetMiscStatus();
2359 test_CoCreateGuid();
2360 test_CoWaitForMultipleHandles();