combase: Return initial values for global options.
[wine.git] / dlls / ole32 / tests / compobj.c
blobd1e947e393f9c345d436d8878c0d033c306bd523
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 "objbase.h"
31 #include "shlguid.h"
32 #include "urlmon.h" /* for CLSID_FileProtocol */
33 #include "dde.h"
34 #include "cguid.h"
36 #include "ctxtcall.h"
38 #include "wine/test.h"
39 #include "winternl.h"
40 #include "initguid.h"
42 #define DEFINE_EXPECT(func) \
43 static BOOL expect_ ## func = FALSE; static unsigned int called_ ## func = 0
45 #define SET_EXPECT(func) \
46 expect_ ## func = TRUE
48 #define CHECK_EXPECT2(func) \
49 do { \
50 ok(expect_ ##func, "unexpected call " #func "\n"); \
51 called_ ## func++; \
52 }while(0)
54 #define CHECK_EXPECT(func) \
55 do { \
56 CHECK_EXPECT2(func); \
57 expect_ ## func = FALSE; \
58 }while(0)
60 #define CHECK_CALLED(func, n) \
61 do { \
62 ok(called_ ## func == n, "expected " #func " called %u times, got %u\n", n, called_ ## func); \
63 expect_ ## func = FALSE; \
64 called_ ## func = 0; \
65 }while(0)
67 DEFINE_EXPECT(CreateStub);
68 DEFINE_EXPECT(PreInitialize);
69 DEFINE_EXPECT(PostInitialize);
70 DEFINE_EXPECT(PreUninitialize);
71 DEFINE_EXPECT(PostUninitialize);
73 /* functions that are not present on all versions of Windows */
74 static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
75 static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
76 static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
77 static HRESULT (WINAPI * pCoGetApartmentType)(APTTYPE *type, APTTYPEQUALIFIER *qualifier);
78 static HRESULT (WINAPI * pCoIncrementMTAUsage)(CO_MTA_USAGE_COOKIE *cookie);
79 static HRESULT (WINAPI * pCoDecrementMTAUsage)(CO_MTA_USAGE_COOKIE cookie);
80 static LONG (WINAPI * pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
81 static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
82 static HRESULT (WINAPI * pCoCreateInstanceFromApp)(REFCLSID clsid, IUnknown *outer, DWORD clscontext,
83 void *reserved, DWORD count, MULTI_QI *results);
85 static BOOL (WINAPI *pIsWow64Process)(HANDLE, LPBOOL);
87 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
88 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
89 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
91 static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
92 static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
93 static const GUID IID_Testiface = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
94 static const GUID IID_Testiface2 = { 0x32222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
95 static const GUID IID_Testiface3 = { 0x42222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
96 static const GUID IID_Testiface4 = { 0x52222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
97 static const GUID IID_Testiface5 = { 0x62222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
98 static const GUID IID_Testiface6 = { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
99 static const GUID IID_Testiface7 = { 0x82222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
100 static const GUID IID_Testiface8 = { 0x92222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
101 static const GUID IID_TestPS = { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } };
103 DEFINE_GUID(CLSID_testclsid, 0xacd014c7,0x9535,0x4fac,0x8b,0x53,0xa4,0x8c,0xa7,0xf4,0xd7,0x26);
105 static const WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
106 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
107 static const WCHAR wszCLSID_StdFont[] =
109 '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
110 '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
112 static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
113 static const WCHAR cf_brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
114 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0};
116 DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
117 DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
119 static LONG cLocks;
121 static void LockModule(void)
123 InterlockedIncrement(&cLocks);
126 static void UnlockModule(void)
128 InterlockedDecrement(&cLocks);
131 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
132 LPCLASSFACTORY iface,
133 REFIID riid,
134 LPVOID *ppvObj)
136 if (ppvObj == NULL) return E_POINTER;
138 if (IsEqualGUID(riid, &IID_IUnknown) ||
139 IsEqualGUID(riid, &IID_IClassFactory))
141 *ppvObj = iface;
142 IClassFactory_AddRef(iface);
143 return S_OK;
146 *ppvObj = NULL;
147 return E_NOINTERFACE;
150 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
152 LockModule();
153 return 2; /* non-heap-based object */
156 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
158 UnlockModule();
159 return 1; /* non-heap-based object */
162 static IID create_instance_iid;
163 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
164 LPCLASSFACTORY iface,
165 IUnknown *pUnkOuter,
166 REFIID riid,
167 LPVOID *ppvObj)
169 *ppvObj = NULL;
170 create_instance_iid = *riid;
171 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
172 return E_NOINTERFACE;
175 static HRESULT WINAPI Test_IClassFactory_LockServer(
176 LPCLASSFACTORY iface,
177 BOOL fLock)
179 return S_OK;
182 static const IClassFactoryVtbl TestClassFactory_Vtbl =
184 Test_IClassFactory_QueryInterface,
185 Test_IClassFactory_AddRef,
186 Test_IClassFactory_Release,
187 Test_IClassFactory_CreateInstance,
188 Test_IClassFactory_LockServer
191 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
193 static WCHAR manifest_path[MAX_PATH];
195 static BOOL create_manifest_file(const char *filename, const char *manifest)
197 int manifest_len;
198 DWORD size;
199 HANDLE file;
200 WCHAR path[MAX_PATH];
202 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
203 GetFullPathNameW(path, ARRAY_SIZE(manifest_path), manifest_path, NULL);
205 manifest_len = strlen(manifest);
206 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
207 FILE_ATTRIBUTE_NORMAL, NULL);
208 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
209 if(file == INVALID_HANDLE_VALUE)
210 return FALSE;
211 WriteFile(file, manifest, manifest_len, &size, NULL);
212 CloseHandle(file);
214 return TRUE;
217 static void extract_resource(const char *name, const char *type, const char *path)
219 DWORD written;
220 HANDLE file;
221 HRSRC res;
222 void *ptr;
224 file = CreateFileA(path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
225 ok(file != INVALID_HANDLE_VALUE, "Failed to create a file at %s, error %d.\n", path, GetLastError());
227 res = FindResourceA(NULL, name, type);
228 ok(res != 0, "Failed to find resource.\n");
229 ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res));
230 WriteFile(file, ptr, SizeofResource(GetModuleHandleA(NULL), res), &written, NULL);
231 ok(written == SizeofResource(GetModuleHandleA(NULL), res), "Failed to write file.\n" );
232 CloseHandle(file);
235 static char testlib[MAX_PATH];
237 static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie)
239 WCHAR path[MAX_PATH];
240 ACTCTXW actctx;
241 HANDLE handle;
242 BOOL ret;
244 create_manifest_file("file.manifest", manifest);
246 MultiByteToWideChar( CP_ACP, 0, "file.manifest", -1, path, MAX_PATH );
247 memset(&actctx, 0, sizeof(ACTCTXW));
248 actctx.cbSize = sizeof(ACTCTXW);
249 actctx.lpSource = path;
251 handle = CreateActCtxW(&actctx);
252 ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* some old XP/2k3 versions */,
253 "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
254 if (handle == INVALID_HANDLE_VALUE)
256 win_skip("activation context generation failed, some tests will be skipped. Error %d\n", GetLastError());
257 handle = NULL;
260 ok(actctx.cbSize == sizeof(ACTCTXW), "actctx.cbSize=%d\n", actctx.cbSize);
261 ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
262 ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
263 ok(actctx.wProcessorArchitecture == 0, "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
264 ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId);
265 ok(actctx.lpAssemblyDirectory == NULL, "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
266 ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
267 ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n", actctx.lpApplicationName);
268 ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
270 DeleteFileA("file.manifest");
272 if (handle)
274 ret = ActivateActCtx(handle, cookie);
275 ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
278 return handle;
281 static void deactivate_context(HANDLE handle, ULONG_PTR cookie)
283 BOOL ret;
285 ret = DeactivateActCtx(0, cookie);
286 ok(ret, "Failed to deactivate context, error %d.\n", GetLastError());
287 ReleaseActCtx(handle);
290 static const char actctx_manifest[] =
291 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
292 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
293 " publicKeyToken=\"6595b6414666f1df\" />"
294 "<file name=\"testlib.dll\">"
295 " <comClass"
296 " clsid=\"{0000033a-0000-0000-c000-000000000046}\""
297 " progid=\"FTMarshal\""
298 " />"
299 " <comClass"
300 " clsid=\"{5201163f-8164-4fd0-a1a2-5d5a3654d3bd}\""
301 " progid=\"WineOOPTest\""
302 " />"
303 " <comClass description=\"Test com class\""
304 " clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
305 " progid=\"ProgId.ProgId\""
306 " miscStatusIcon=\"recomposeonresize\""
307 " />"
308 " <comClass description=\"CustomFont Description\" clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb851}\""
309 " progid=\"CustomFont\""
310 " miscStatusIcon=\"recomposeonresize\""
311 " miscStatusContent=\"insideout\""
312 " />"
313 " <comClass description=\"StdFont Description\" clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
314 " progid=\"StdFont\""
315 " />"
316 " <comClass clsid=\"{62222222-1234-1234-1234-56789abcdef0}\" >"
317 " <progid>ProgId.ProgId.1</progid>"
318 " </comClass>"
319 " <comInterfaceProxyStub "
320 " name=\"Iifaceps\""
321 " iid=\"{22222222-1234-1234-1234-56789abcdef0}\""
322 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
323 " />"
324 " <comInterfaceProxyStub "
325 " name=\"Iifaceps5\""
326 " iid=\"{82222222-1234-1234-1234-56789abcdef0}\""
327 " />"
328 "</file>"
329 " <comInterfaceExternalProxyStub "
330 " name=\"Iifaceps2\""
331 " iid=\"{32222222-1234-1234-1234-56789abcdef0}\""
332 " />"
333 " <comInterfaceExternalProxyStub "
334 " name=\"Iifaceps3\""
335 " iid=\"{42222222-1234-1234-1234-56789abcdef0}\""
336 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
337 " />"
338 " <comInterfaceExternalProxyStub "
339 " name=\"Iifaceps4\""
340 " iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
341 " proxyStubClsid32=\"{00000000-0000-0000-0000-000000000000}\""
342 " />"
343 " <clrClass "
344 " clsid=\"{72222222-1234-1234-1234-56789abcdef0}\""
345 " name=\"clrclass\""
346 " >"
347 " <progid>clrprogid.1</progid>"
348 " </clrClass>"
349 "</assembly>";
351 static const char actctx_manifest2[] =
352 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
353 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
354 " publicKeyToken=\"6595b6414666f1df\" />"
355 "<file name=\"testlib.dll\">"
356 " <comInterfaceProxyStub "
357 " name=\"Testiface7\""
358 " iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
359 " proxyStubClsid32=\"{82222222-1234-1234-1234-56789abcdef0}\""
360 " threadingModel=\"Apartment\""
361 " />"
362 "</file>"
363 "<file name=\"testlib4.dll\">"
364 " <comInterfaceProxyStub "
365 " name=\"Testiface8\""
366 " iid=\"{92222222-1234-1234-1234-56789abcdef0}\""
367 " threadingModel=\"Apartment\""
368 " />"
369 "</file>"
370 " <comInterfaceExternalProxyStub "
371 " name=\"Iifaceps3\""
372 " iid=\"{42222222-1234-1234-1234-56789abcdef0}\""
373 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
374 " />"
375 "</assembly>";
377 DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
379 static void test_ProgIDFromCLSID(void)
381 ULONG_PTR cookie = 0;
382 LPWSTR progid;
383 HANDLE handle;
384 HRESULT hr;
386 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
387 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
388 if (hr == S_OK)
390 ok(!lstrcmpiW(progid, stdfont), "Didn't get expected prog ID\n");
391 CoTaskMemFree(progid);
394 progid = (LPWSTR)0xdeadbeef;
395 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
396 ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
397 ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
399 hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
400 ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
402 if ((handle = activate_context(actctx_manifest, &cookie)))
404 static const WCHAR customfontW[] = {'C','u','s','t','o','m','F','o','n','t',0};
406 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
407 ok(hr == S_OK, "got 0x%08x\n", hr);
408 ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid));
409 CoTaskMemFree(progid);
411 /* try something registered and redirected */
412 progid = NULL;
413 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
414 ok(hr == S_OK, "got 0x%08x\n", hr);
415 ok(!lstrcmpiW(progid, customfontW), "got wrong progid %s\n", wine_dbgstr_w(progid));
416 CoTaskMemFree(progid);
418 /* classes without default progid, progid list is not used */
419 progid = (void *)0xdeadbeef;
420 hr = ProgIDFromCLSID(&IID_Testiface5, &progid);
421 ok(hr == REGDB_E_CLASSNOTREG && progid == NULL, "got 0x%08x, progid %p\n", hr, progid);
423 progid = (void *)0xdeadbeef;
424 hr = ProgIDFromCLSID(&IID_Testiface6, &progid);
425 ok(hr == REGDB_E_CLASSNOTREG && progid == NULL, "got 0x%08x, progid %p\n", hr, progid);
427 deactivate_context(handle, cookie);
431 static void test_CLSIDFromProgID(void)
433 ULONG_PTR cookie = 0;
434 HANDLE handle;
435 CLSID clsid;
436 HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
437 ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
438 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
440 hr = CLSIDFromString(stdfont, &clsid);
441 ok_ole_success(hr, "CLSIDFromString");
442 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
444 /* test some failure cases */
446 hr = CLSIDFromProgID(wszNonExistent, NULL);
447 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
449 hr = CLSIDFromProgID(NULL, &clsid);
450 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
452 memset(&clsid, 0xcc, sizeof(clsid));
453 hr = CLSIDFromProgID(wszNonExistent, &clsid);
454 ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
455 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
457 /* fails without proper context */
458 memset(&clsid, 0xcc, sizeof(clsid));
459 hr = CLSIDFromProgID(progidW, &clsid);
460 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
461 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "wrong clsid\n");
463 if ((handle = activate_context(actctx_manifest, &cookie)))
465 GUID clsid1;
467 memset(&clsid, 0xcc, sizeof(clsid));
468 hr = CLSIDFromProgID(wszNonExistent, &clsid);
469 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
470 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "should have zero CLSID on failure\n");
472 /* CLSIDFromString() doesn't check activation context */
473 hr = CLSIDFromString(progidW, &clsid);
474 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
476 clsid = CLSID_NULL;
477 hr = CLSIDFromProgID(progidW, &clsid);
478 ok(hr == S_OK, "got 0x%08x\n", hr);
479 /* it returns generated CLSID here */
480 ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL),
481 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid));
483 /* duplicate progid present in context - returns generated guid here too */
484 clsid = CLSID_NULL;
485 hr = CLSIDFromProgID(stdfont, &clsid);
486 ok(hr == S_OK, "got 0x%08x\n", hr);
487 clsid1 = CLSID_StdFont;
488 /* that's where it differs from StdFont */
489 clsid1.Data4[7] = 0x52;
490 ok(!IsEqualCLSID(&clsid, &CLSID_StdFont) && !IsEqualCLSID(&clsid, &CLSID_NULL) && !IsEqualCLSID(&clsid, &clsid1),
491 "got %s\n", wine_dbgstr_guid(&clsid));
493 deactivate_context(handle, cookie);
497 static void test_CLSIDFromString(void)
499 CLSID clsid;
500 WCHAR wszCLSID_Broken[50];
501 UINT i;
503 HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
504 ok_ole_success(hr, "CLSIDFromString");
505 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
507 memset(&clsid, 0xab, sizeof(clsid));
508 hr = CLSIDFromString(NULL, &clsid);
509 ok(hr == S_OK, "got 0x%08x\n", hr);
510 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
512 /* string is longer, but starts with a valid CLSID */
513 memset(&clsid, 0, sizeof(clsid));
514 hr = CLSIDFromString(cf_brokenW, &clsid);
515 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
516 ok(IsEqualCLSID(&clsid, &IID_IClassFactory), "got %s\n", wine_dbgstr_guid(&clsid));
518 lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
519 for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
520 wszCLSID_Broken[i] = 'A';
521 wszCLSID_Broken[i] = '\0';
523 memset(&clsid, 0, sizeof(CLSID));
524 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
525 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
526 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
528 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
529 memset(&clsid, 0, sizeof(CLSID));
530 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
531 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
532 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
534 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
535 memset(&clsid, 0, sizeof(CLSID));
536 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
537 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
538 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
540 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
541 memset(&clsid, 0, sizeof(CLSID));
542 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
543 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
544 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
546 memset(&clsid, 0xcc, sizeof(CLSID));
547 hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
548 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
549 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
551 wszCLSID_Broken[9] = '*';
552 memset(&clsid, 0xcc, sizeof(CLSID));
553 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
554 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
555 ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
556 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
558 wszCLSID_Broken[3] = '*';
559 memset(&clsid, 0xcc, sizeof(CLSID));
560 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
561 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
562 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
563 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
565 wszCLSID_Broken[3] = '\0';
566 memset(&clsid, 0xcc, sizeof(CLSID));
567 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
568 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
569 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
570 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
573 static void test_IIDFromString(void)
575 static const WCHAR cfW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
576 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
577 static const WCHAR brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
578 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
579 static const WCHAR broken2W[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
580 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
581 static const WCHAR broken3W[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
582 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
583 HRESULT hr;
584 IID iid;
586 hr = IIDFromString(wszCLSID_StdFont, &iid);
587 ok(hr == S_OK, "got 0x%08x\n", hr);
588 ok(IsEqualIID(&iid, &CLSID_StdFont), "got iid %s\n", wine_dbgstr_guid(&iid));
590 memset(&iid, 0xab, sizeof(iid));
591 hr = IIDFromString(NULL, &iid);
592 ok(hr == S_OK, "got 0x%08x\n", hr);
593 ok(IsEqualIID(&iid, &CLSID_NULL), "got iid %s\n", wine_dbgstr_guid(&iid));
595 hr = IIDFromString(cfW, &iid);
596 ok(hr == S_OK, "got 0x%08x\n", hr);
597 ok(IsEqualIID(&iid, &IID_IClassFactory), "got iid %s\n", wine_dbgstr_guid(&iid));
599 /* string starts with a valid IID but is longer */
600 memset(&iid, 0xab, sizeof(iid));
601 hr = IIDFromString(cf_brokenW, &iid);
602 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
603 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
605 /* invalid IID in a valid format */
606 memset(&iid, 0xab, sizeof(iid));
607 hr = IIDFromString(brokenW, &iid);
608 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
609 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
611 memset(&iid, 0xab, sizeof(iid));
612 hr = IIDFromString(broken2W, &iid);
613 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
614 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
616 /* format is broken, but string length is okay */
617 memset(&iid, 0xab, sizeof(iid));
618 hr = IIDFromString(broken3W, &iid);
619 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
620 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
622 /* invalid string */
623 memset(&iid, 0xab, sizeof(iid));
624 hr = IIDFromString(wszNonExistent, &iid);
625 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
626 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
628 /* valid ProgID */
629 memset(&iid, 0xab, sizeof(iid));
630 hr = IIDFromString(stdfont, &iid);
631 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
632 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
635 static void test_StringFromGUID2(void)
637 WCHAR str[50];
638 int len;
640 /* invalid pointer */
641 SetLastError(0xdeadbeef);
642 len = StringFromGUID2(NULL,str,50);
643 ok(len == 0, "len: %d (expected 0)\n", len);
644 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
646 /* Test corner cases for buffer size */
647 len = StringFromGUID2(&CLSID_StdFont,str,50);
648 ok(len == 39, "len: %d (expected 39)\n", len);
649 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
651 memset(str,0,sizeof str);
652 len = StringFromGUID2(&CLSID_StdFont,str,39);
653 ok(len == 39, "len: %d (expected 39)\n", len);
654 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
656 len = StringFromGUID2(&CLSID_StdFont,str,38);
657 ok(len == 0, "len: %d (expected 0)\n", len);
659 len = StringFromGUID2(&CLSID_StdFont,str,30);
660 ok(len == 0, "len: %d (expected 0)\n", len);
663 #define test_apt_type(t, q) _test_apt_type(t, q, __LINE__)
664 static void _test_apt_type(APTTYPE expected_type, APTTYPEQUALIFIER expected_qualifier, int line)
666 APTTYPEQUALIFIER qualifier = ~0u;
667 APTTYPE type = ~0u;
668 HRESULT hr;
670 if (!pCoGetApartmentType)
671 return;
673 hr = pCoGetApartmentType(&type, &qualifier);
674 ok_(__FILE__, line)(hr == S_OK || (type == APTTYPE_CURRENT && hr == CO_E_NOTINITIALIZED),
675 "Unexpected hr %#x.\n", hr);
676 ok_(__FILE__, line)(type == expected_type, "Wrong apartment type %d, expected %d\n", type, expected_type);
677 ok_(__FILE__, line)(qualifier == expected_qualifier, "Wrong apartment qualifier %d, expected %d\n", qualifier,
678 expected_qualifier);
681 static void test_CoCreateInstance(void)
683 HRESULT hr;
684 IUnknown *pUnk;
685 REFCLSID rclsid = &CLSID_InternetZoneManager;
687 pUnk = (IUnknown *)0xdeadbeef;
688 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
689 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
690 ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
692 OleInitialize(NULL);
694 /* test errors returned for non-registered clsids */
695 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
696 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
697 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pUnk);
698 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
699 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (void **)&pUnk);
700 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
701 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_REMOTE_SERVER, &IID_IUnknown, (void **)&pUnk);
702 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
704 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
705 if(hr == REGDB_E_CLASSNOTREG)
707 skip("IE not installed so can't test CoCreateInstance\n");
708 OleUninitialize();
709 return;
712 ok_ole_success(hr, "CoCreateInstance");
713 if(pUnk) IUnknown_Release(pUnk);
714 OleUninitialize();
716 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
717 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
719 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
722 struct comclassredirect_data
724 ULONG size;
725 ULONG flags;
726 DWORD model;
727 GUID clsid;
728 GUID alias;
729 GUID clsid2;
730 GUID tlid;
731 ULONG name_len;
732 ULONG name_offset;
733 ULONG progid_len;
734 ULONG progid_offset;
735 ULONG clrdata_len;
736 ULONG clrdata_offset;
737 DWORD miscstatus;
738 DWORD miscstatuscontent;
739 DWORD miscstatusthumbnail;
740 DWORD miscstatusicon;
741 DWORD miscstatusdocprint;
744 static void test_CoGetClassObject(void)
746 HRESULT hr;
747 HANDLE handle;
748 ULONG_PTR cookie;
749 IUnknown *pUnk;
750 REFCLSID rclsid = &CLSID_InternetZoneManager;
751 HKEY hkey;
752 LONG res;
754 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
755 ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
756 ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
758 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
759 ok(hr == E_INVALIDARG ||
760 broken(hr == CO_E_NOTINITIALIZED), /* win9x */
761 "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
763 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
765 if (!pRegOverridePredefKey)
767 win_skip("RegOverridePredefKey not available\n");
768 return;
771 CoInitializeEx(NULL, COINIT_MULTITHREADED);
773 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
774 if (hr == S_OK)
776 IUnknown_Release(pUnk);
778 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
779 KEY_ALL_ACCESS, NULL, &hkey, NULL);
780 ok(!res, "RegCreateKeyEx returned %d\n", res);
782 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
783 ok(!res, "RegOverridePredefKey returned %d\n", res);
785 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
786 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
788 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
789 ok(!res, "RegOverridePredefKey returned %d\n", res);
791 if (hr == S_OK) IUnknown_Release(pUnk);
792 RegCloseKey(hkey);
795 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
796 ok(hr == S_OK, "got 0x%08x\n", hr);
797 IUnknown_Release(pUnk);
799 /* context redefines FreeMarshaler CLSID */
800 if ((handle = activate_context(actctx_manifest, &cookie)))
802 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
803 ok(hr == S_OK, "got 0x%08x\n", hr);
804 IUnknown_Release(pUnk);
806 hr = CoGetClassObject(&IID_Testiface7, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
807 ok(hr == 0x80001235 || broken(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND)) /* winxp */, "Unexpected hr %#x.\n", hr);
809 hr = CoGetClassObject(&IID_Testiface8, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
810 ok(hr == REGDB_E_CLASSNOTREG, "Unexpected hr %#x.\n", hr);
812 deactivate_context(handle, cookie);
815 if ((handle = activate_context(actctx_manifest2, &cookie)))
817 struct comclassredirect_data *comclass;
818 ACTCTX_SECTION_KEYED_DATA data;
819 BOOL ret;
821 /* This one will load test dll and get back specific error code. */
822 hr = CoGetClassObject(&IID_Testiface7, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
823 ok(hr == 0x80001235 || broken(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND)) /* winxp */, "Unexpected hr %#x.\n", hr);
825 hr = CoGetClassObject(&IID_Testiface8, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
826 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
828 memset(&data, 0, sizeof(data));
829 data.cbSize = sizeof(data);
830 ret = FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION, &IID_Testiface8, &data);
831 ok(ret, "Section not found.\n");
833 memset(&data, 0, sizeof(data));
834 data.cbSize = sizeof(data);
836 /* External proxy-stubs are not accessible. */
837 ret = FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, &IID_Testiface3, &data);
838 ok(!ret, "Unexpected return value.\n");
840 ret = FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, &IID_TestPS, &data);
841 ok(!ret, "Unexpected return value.\n");
843 ret = FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, &IID_Testiface7, &data);
844 ok(ret, "Unexpected return value.\n");
846 ret = FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, &IID_Testiface4, &data);
847 ok(!ret, "Unexpected return value.\n");
849 ret = FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, &IID_Testiface8, &data);
850 ok(ret, "Unexpected return value.\n");
852 comclass = data.lpData;
853 if (comclass)
855 WCHAR *name = (WCHAR *)((char *)data.lpSectionBase + comclass->name_offset);
856 ok(!lstrcmpW(name, L"testlib4.dll"), "Unexpected module name %s.\n", wine_dbgstr_w(name));
859 deactivate_context(handle, cookie);
862 CoUninitialize();
865 static void test_CoCreateInstanceEx(void)
867 MULTI_QI qi_res = { &IID_IMoniker };
868 DWORD cookie;
869 HRESULT hr;
871 CoInitialize(NULL);
873 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
874 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
875 ok_ole_success(hr, "CoRegisterClassObject");
877 create_instance_iid = IID_NULL;
878 hr = CoCreateInstanceEx(&CLSID_WineOOPTest, NULL, CLSCTX_INPROC_SERVER, NULL, 1, &qi_res);
879 ok(hr == E_NOINTERFACE, "CoCreateInstanceEx failed: %08x\n", hr);
880 ok(IsEqualGUID(&create_instance_iid, qi_res.pIID), "Unexpected CreateInstance iid %s\n",
881 wine_dbgstr_guid(&create_instance_iid));
883 hr = CoRevokeClassObject(cookie);
884 ok_ole_success(hr, "CoRevokeClassObject");
886 CoUninitialize();
889 static ATOM register_dummy_class(void)
891 WNDCLASSA wc =
894 DefWindowProcA,
897 GetModuleHandleA(NULL),
898 NULL,
899 LoadCursorA(NULL, (LPSTR)IDC_ARROW),
900 (HBRUSH)(COLOR_BTNFACE+1),
901 NULL,
902 "WineOleTestClass",
905 return RegisterClassA(&wc);
908 static void test_ole_menu(void)
910 HWND hwndFrame;
911 HRESULT hr;
913 hwndFrame = CreateWindowA((LPCSTR)MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
914 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
915 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
917 DestroyWindow(hwndFrame);
921 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
923 if (ppvObj == NULL) return E_POINTER;
925 if (IsEqualGUID(riid, &IID_IUnknown) ||
926 IsEqualGUID(riid, &IID_IMessageFilter))
928 *ppvObj = iface;
929 IMessageFilter_AddRef(iface);
930 return S_OK;
933 return E_NOINTERFACE;
936 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
938 return 2; /* non-heap object */
941 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
943 return 1; /* non-heap object */
946 static DWORD WINAPI MessageFilter_HandleInComingCall(
947 IMessageFilter *iface,
948 DWORD dwCallType,
949 HTASK threadIDCaller,
950 DWORD dwTickCount,
951 LPINTERFACEINFO lpInterfaceInfo)
953 trace("HandleInComingCall\n");
954 return SERVERCALL_ISHANDLED;
957 static DWORD WINAPI MessageFilter_RetryRejectedCall(
958 IMessageFilter *iface,
959 HTASK threadIDCallee,
960 DWORD dwTickCount,
961 DWORD dwRejectType)
963 trace("RetryRejectedCall\n");
964 return 0;
967 static DWORD WINAPI MessageFilter_MessagePending(
968 IMessageFilter *iface,
969 HTASK threadIDCallee,
970 DWORD dwTickCount,
971 DWORD dwPendingType)
973 trace("MessagePending\n");
974 todo_wine ok(0, "unexpected call\n");
975 return PENDINGMSG_WAITNOPROCESS;
978 static const IMessageFilterVtbl MessageFilter_Vtbl =
980 MessageFilter_QueryInterface,
981 MessageFilter_AddRef,
982 MessageFilter_Release,
983 MessageFilter_HandleInComingCall,
984 MessageFilter_RetryRejectedCall,
985 MessageFilter_MessagePending
988 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
990 static void test_CoRegisterMessageFilter(void)
992 HRESULT hr;
993 IMessageFilter *prev_filter;
995 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
996 ok(hr == CO_E_NOT_SUPPORTED,
997 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
998 hr);
1000 CoInitializeEx(NULL, COINIT_MULTITHREADED);
1001 prev_filter = (IMessageFilter *)0xdeadbeef;
1002 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1003 ok(hr == CO_E_NOT_SUPPORTED,
1004 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
1005 hr);
1006 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
1007 "prev_filter should have been set to %p\n", prev_filter);
1008 CoUninitialize();
1010 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1012 hr = CoRegisterMessageFilter(NULL, NULL);
1013 ok_ole_success(hr, "CoRegisterMessageFilter");
1015 prev_filter = (IMessageFilter *)0xdeadbeef;
1016 hr = CoRegisterMessageFilter(NULL, &prev_filter);
1017 ok_ole_success(hr, "CoRegisterMessageFilter");
1018 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
1020 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1021 ok_ole_success(hr, "CoRegisterMessageFilter");
1022 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
1024 hr = CoRegisterMessageFilter(NULL, NULL);
1025 ok_ole_success(hr, "CoRegisterMessageFilter");
1027 CoUninitialize();
1030 static IUnknown Test_Unknown;
1032 static HRESULT WINAPI EnumOLEVERB_QueryInterface(IEnumOLEVERB *iface, REFIID riid, void **ppv)
1034 return IUnknown_QueryInterface(&Test_Unknown, riid, ppv);
1037 static ULONG WINAPI EnumOLEVERB_AddRef(IEnumOLEVERB *iface)
1039 return 2;
1042 static ULONG WINAPI EnumOLEVERB_Release(IEnumOLEVERB *iface)
1044 return 1;
1047 static HRESULT WINAPI EnumOLEVERB_Next(IEnumOLEVERB *iface, ULONG celt, OLEVERB *rgelt, ULONG *fetched)
1049 ok(0, "unexpected call\n");
1050 return E_NOTIMPL;
1053 static HRESULT WINAPI EnumOLEVERB_Skip(IEnumOLEVERB *iface, ULONG celt)
1055 ok(0, "unexpected call\n");
1056 return E_NOTIMPL;
1059 static HRESULT WINAPI EnumOLEVERB_Reset(IEnumOLEVERB *iface)
1061 ok(0, "unexpected call\n");
1062 return E_NOTIMPL;
1065 static HRESULT WINAPI EnumOLEVERB_Clone(IEnumOLEVERB *iface, IEnumOLEVERB **ppenum)
1067 ok(0, "unexpected call\n");
1068 return E_NOTIMPL;
1071 static const IEnumOLEVERBVtbl EnumOLEVERBVtbl = {
1072 EnumOLEVERB_QueryInterface,
1073 EnumOLEVERB_AddRef,
1074 EnumOLEVERB_Release,
1075 EnumOLEVERB_Next,
1076 EnumOLEVERB_Skip,
1077 EnumOLEVERB_Reset,
1078 EnumOLEVERB_Clone
1081 static IEnumOLEVERB EnumOLEVERB = { &EnumOLEVERBVtbl };
1083 static HRESULT WINAPI Test_IUnknown_QueryInterface(
1084 IUnknown *iface,
1085 REFIID riid,
1086 LPVOID *ppvObj)
1088 if (ppvObj == NULL) return E_POINTER;
1090 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IWineTest)) {
1091 *ppvObj = iface;
1092 }else if(IsEqualIID(riid, &IID_IEnumOLEVERB)) {
1093 *ppvObj = &EnumOLEVERB;
1094 }else {
1095 *ppvObj = NULL;
1096 return E_NOINTERFACE;
1099 IUnknown_AddRef((IUnknown*)*ppvObj);
1100 return S_OK;
1103 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
1105 return 2; /* non-heap-based object */
1108 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
1110 return 1; /* non-heap-based object */
1113 static const IUnknownVtbl TestUnknown_Vtbl =
1115 Test_IUnknown_QueryInterface,
1116 Test_IUnknown_AddRef,
1117 Test_IUnknown_Release,
1120 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
1122 static IPSFactoryBuffer *ps_factory_buffer;
1124 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
1125 IPSFactoryBuffer * This,
1126 /* [in] */ REFIID riid,
1127 /* [iid_is][out] */ void **ppvObject)
1129 if (IsEqualIID(riid, &IID_IUnknown) ||
1130 IsEqualIID(riid, &IID_IPSFactoryBuffer))
1132 *ppvObject = This;
1133 IPSFactoryBuffer_AddRef(This);
1134 return S_OK;
1136 return E_NOINTERFACE;
1139 static ULONG WINAPI PSFactoryBuffer_AddRef(
1140 IPSFactoryBuffer * This)
1142 return 2;
1145 static ULONG WINAPI PSFactoryBuffer_Release(
1146 IPSFactoryBuffer * This)
1148 return 1;
1151 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
1152 IPSFactoryBuffer * This,
1153 /* [in] */ IUnknown *pUnkOuter,
1154 /* [in] */ REFIID riid,
1155 /* [out] */ IRpcProxyBuffer **ppProxy,
1156 /* [out] */ void **ppv)
1158 return E_NOTIMPL;
1161 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
1162 IPSFactoryBuffer * This,
1163 /* [in] */ REFIID riid,
1164 /* [unique][in] */ IUnknown *pUnkServer,
1165 /* [out] */ IRpcStubBuffer **ppStub)
1167 CHECK_EXPECT(CreateStub);
1169 ok(pUnkServer == &Test_Unknown, "unexpected pUnkServer %p\n", pUnkServer);
1170 if(!ps_factory_buffer)
1171 return E_NOTIMPL;
1173 return IPSFactoryBuffer_CreateStub(ps_factory_buffer, &IID_IEnumOLEVERB, pUnkServer, ppStub);
1176 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
1178 PSFactoryBuffer_QueryInterface,
1179 PSFactoryBuffer_AddRef,
1180 PSFactoryBuffer_Release,
1181 PSFactoryBuffer_CreateProxy,
1182 PSFactoryBuffer_CreateStub
1185 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
1187 static const CLSID CLSID_WineTestPSFactoryBuffer =
1189 0x52011640,
1190 0x8164,
1191 0x4fd0,
1192 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1193 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
1195 static DWORD CALLBACK register_ps_clsid_thread(void *context)
1197 HRESULT hr;
1198 CLSID clsid = {0};
1200 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1202 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1203 ok_ole_success(hr, "CoGetPSClsid");
1204 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1205 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1207 /* test registering a PSClsid in an apartment which is then destroyed */
1208 hr = CoRegisterPSClsid(&IID_TestPS, &clsid);
1209 ok_ole_success(hr, "CoRegisterPSClsid");
1211 CoUninitialize();
1213 return hr;
1216 static void test_CoRegisterPSClsid(void)
1218 HRESULT hr;
1219 DWORD dwRegistrationKey;
1220 IStream *stream;
1221 CLSID clsid;
1222 HANDLE thread;
1223 DWORD tid;
1225 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1226 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1228 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1230 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
1231 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
1232 ok_ole_success(hr, "CoRegisterClassObject");
1234 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1235 ok_ole_success(hr, "CoRegisterPSClsid");
1237 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1238 ok_ole_success(hr, "CoGetPSClsid");
1239 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1240 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1242 thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid);
1243 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1244 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
1245 CloseHandle(thread);
1247 hr = CoGetPSClsid(&IID_TestPS, &clsid);
1248 ok_ole_success(hr, "CoGetPSClsid");
1249 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1250 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1252 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1253 ok_ole_success(hr, "CreateStreamOnHGlobal");
1255 SET_EXPECT(CreateStub);
1256 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1257 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1258 CHECK_CALLED(CreateStub, 1);
1260 hr = CoGetPSClsid(&IID_IEnumOLEVERB, &clsid);
1261 ok_ole_success(hr, "CoGetPSClsid");
1263 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void **)&ps_factory_buffer);
1264 ok_ole_success(hr, "CoGetClassObject");
1266 hr = CoRegisterPSClsid(&IID_IEnumOLEVERB, &CLSID_WineTestPSFactoryBuffer);
1267 ok_ole_success(hr, "CoRegisterPSClsid");
1269 SET_EXPECT(CreateStub);
1270 hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1271 ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
1272 CHECK_CALLED(CreateStub, 1);
1274 hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1275 ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
1277 IStream_Release(stream);
1278 IPSFactoryBuffer_Release(ps_factory_buffer);
1279 ps_factory_buffer = NULL;
1281 hr = CoRevokeClassObject(dwRegistrationKey);
1282 ok_ole_success(hr, "CoRevokeClassObject");
1284 CoUninitialize();
1286 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1288 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1289 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
1291 hr = CoGetPSClsid(&IID_TestPS, &clsid);
1292 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
1294 CoUninitialize();
1296 CoInitializeEx(NULL, COINIT_MULTITHREADED);
1298 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1299 ok_ole_success(hr, "CoRegisterPSClsid");
1301 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1302 ok_ole_success(hr, "CoGetPSClsid");
1303 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1304 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1306 thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid);
1307 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1308 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
1309 CloseHandle(thread);
1311 hr = CoGetPSClsid(&IID_TestPS, &clsid);
1312 ok_ole_success(hr, "CoGetPSClsid");
1313 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1314 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1316 CoUninitialize();
1319 static void test_CoGetPSClsid(void)
1321 ULONG_PTR cookie;
1322 HANDLE handle;
1323 HRESULT hr;
1324 CLSID clsid;
1325 HKEY hkey;
1326 LONG res;
1327 const BOOL is_win64 = (sizeof(void*) != sizeof(int));
1328 BOOL is_wow64 = FALSE;
1330 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1331 ok(hr == CO_E_NOTINITIALIZED,
1332 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
1333 hr);
1335 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1337 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1338 ok_ole_success(hr, "CoGetPSClsid");
1340 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1341 ok(hr == REGDB_E_IIDNOTREG,
1342 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
1343 hr);
1345 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
1346 ok(hr == E_INVALIDARG,
1347 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
1348 hr);
1350 if (!pRegOverridePredefKey)
1352 win_skip("RegOverridePredefKey not available\n");
1353 CoUninitialize();
1354 return;
1356 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1357 ok_ole_success(hr, "CoGetPSClsid");
1359 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
1360 KEY_ALL_ACCESS, NULL, &hkey, NULL);
1361 ok(!res, "RegCreateKeyEx returned %d\n", res);
1363 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
1364 ok(!res, "RegOverridePredefKey returned %d\n", res);
1366 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1367 ok_ole_success(hr, "CoGetPSClsid");
1369 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
1370 ok(!res, "RegOverridePredefKey returned %d\n", res);
1372 RegCloseKey(hkey);
1374 /* not registered CLSID */
1375 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1376 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1378 if ((handle = activate_context(actctx_manifest, &cookie)))
1380 memset(&clsid, 0, sizeof(clsid));
1381 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1382 ok(hr == S_OK, "got 0x%08x\n", hr);
1383 ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1385 memset(&clsid, 0, sizeof(clsid));
1386 hr = CoGetPSClsid(&IID_Testiface2, &clsid);
1387 ok(hr == S_OK, "got 0x%08x\n", hr);
1388 ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1390 memset(&clsid, 0, sizeof(clsid));
1391 hr = CoGetPSClsid(&IID_Testiface3, &clsid);
1392 ok(hr == S_OK, "got 0x%08x\n", hr);
1393 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1395 memset(&clsid, 0xaa, sizeof(clsid));
1396 hr = CoGetPSClsid(&IID_Testiface4, &clsid);
1397 ok(hr == S_OK, "got 0x%08x\n", hr);
1398 ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1400 memset(&clsid, 0xaa, sizeof(clsid));
1401 hr = CoGetPSClsid(&IID_Testiface7, &clsid);
1402 ok(hr == S_OK, "Failed to get PS CLSID, hr %#x.\n", hr);
1403 ok(IsEqualGUID(&clsid, &IID_Testiface7), "Unexpected CLSID %s.\n", wine_dbgstr_guid(&clsid));
1405 /* register same interface and try to get CLSID back */
1406 hr = CoRegisterPSClsid(&IID_Testiface, &IID_Testiface4);
1407 ok(hr == S_OK, "got 0x%08x\n", hr);
1408 memset(&clsid, 0, sizeof(clsid));
1409 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1410 ok(hr == S_OK, "got 0x%08x\n", hr);
1411 ok(IsEqualGUID(&clsid, &IID_Testiface4), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1413 deactivate_context(handle, cookie);
1416 if (pRegDeleteKeyExA &&
1417 (is_win64 ||
1418 (pIsWow64Process && pIsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
1420 static GUID IID_DeadBeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1421 static const char clsidDeadBeef[] = "{deadbeef-dead-beef-dead-beefdeadbeef}";
1422 static const char clsidA[] = "{66666666-8888-7777-6666-555555555555}";
1423 HKEY hkey_iface, hkey_psclsid;
1424 REGSAM opposite = is_win64 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
1426 hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1427 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1429 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, "Interface",
1430 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_iface, NULL);
1431 ok(!res, "RegCreateKeyEx returned %d\n", res);
1432 res = RegCreateKeyExA(hkey_iface, clsidDeadBeef,
1433 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey, NULL);
1434 if (res == ERROR_ACCESS_DENIED)
1436 win_skip("Failed to create a key, skipping some of CoGetPSClsid() tests\n");
1437 goto cleanup;
1440 ok(!res, "RegCreateKeyEx returned %d\n", res);
1441 res = RegCreateKeyExA(hkey, "ProxyStubClsid32",
1442 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_psclsid, NULL);
1443 ok(!res, "RegCreateKeyEx returned %d\n", res);
1444 res = RegSetValueExA(hkey_psclsid, NULL, 0, REG_SZ, (const BYTE *)clsidA, strlen(clsidA)+1);
1445 ok(!res, "RegSetValueEx returned %d\n", res);
1446 RegCloseKey(hkey_psclsid);
1448 hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1449 ok_ole_success(hr, "CoGetPSClsid");
1450 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1452 res = pRegDeleteKeyExA(hkey, "ProxyStubClsid32", opposite, 0);
1453 ok(!res, "RegDeleteKeyEx returned %d\n", res);
1454 RegCloseKey(hkey);
1455 res = pRegDeleteKeyExA(hkey_iface, clsidDeadBeef, opposite, 0);
1456 ok(!res, "RegDeleteKeyEx returned %d\n", res);
1458 cleanup:
1459 RegCloseKey(hkey_iface);
1462 CoUninitialize();
1465 /* basic test, mainly for invalid arguments. see marshal.c for more */
1466 static void test_CoUnmarshalInterface(void)
1468 IUnknown *pProxy;
1469 IStream *pStream;
1470 HRESULT hr;
1472 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
1473 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1475 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1476 ok_ole_success(hr, "CreateStreamOnHGlobal");
1478 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1479 todo_wine
1480 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1482 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1484 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1485 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1487 CoUninitialize();
1489 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
1490 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1492 IStream_Release(pStream);
1495 static void test_CoGetInterfaceAndReleaseStream(void)
1497 HRESULT hr;
1498 IUnknown *pUnk;
1500 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1502 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
1503 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
1505 CoUninitialize();
1508 /* basic test, mainly for invalid arguments. see marshal.c for more */
1509 static void test_CoMarshalInterface(void)
1511 IStream *pStream;
1512 HRESULT hr;
1513 static const LARGE_INTEGER llZero;
1515 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1517 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1518 ok_ole_success(hr, "CreateStreamOnHGlobal");
1520 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1521 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1523 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1524 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1526 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1527 ok_ole_success(hr, "CoMarshalInterface");
1529 /* stream not rewound */
1530 hr = CoReleaseMarshalData(pStream);
1531 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1533 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1534 ok_ole_success(hr, "IStream_Seek");
1536 hr = CoReleaseMarshalData(pStream);
1537 ok_ole_success(hr, "CoReleaseMarshalData");
1539 IStream_Release(pStream);
1541 CoUninitialize();
1544 static void test_CoMarshalInterThreadInterfaceInStream(void)
1546 IStream *pStream;
1547 HRESULT hr;
1548 IClassFactory *pProxy;
1550 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1552 cLocks = 0;
1554 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
1555 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1557 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
1558 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1560 ok_no_locks();
1562 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
1563 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
1565 ok_more_than_one_lock();
1567 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1568 ok_ole_success(hr, "CoUnmarshalInterface");
1570 IClassFactory_Release(pProxy);
1571 IStream_Release(pStream);
1573 ok_no_locks();
1575 CoUninitialize();
1578 static void test_CoRegisterClassObject(void)
1580 ULONG_PTR ctxcookie;
1581 HANDLE handle;
1582 DWORD cookie;
1583 HRESULT hr;
1584 IClassFactory *pcf;
1586 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1588 /* CLSCTX_INPROC_SERVER */
1589 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1590 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1591 ok_ole_success(hr, "CoRegisterClassObject");
1592 hr = CoRevokeClassObject(cookie);
1593 ok_ole_success(hr, "CoRevokeClassObject");
1595 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1596 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1597 ok_ole_success(hr, "CoRegisterClassObject");
1598 hr = CoRevokeClassObject(cookie);
1599 ok_ole_success(hr, "CoRevokeClassObject");
1601 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1602 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1603 ok_ole_success(hr, "CoRegisterClassObject");
1604 hr = CoRevokeClassObject(cookie);
1605 ok_ole_success(hr, "CoRevokeClassObject");
1607 /* CLSCTX_LOCAL_SERVER */
1608 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1609 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1610 ok_ole_success(hr, "CoRegisterClassObject");
1611 hr = CoRevokeClassObject(cookie);
1612 ok_ole_success(hr, "CoRevokeClassObject");
1614 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1615 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1616 ok_ole_success(hr, "CoRegisterClassObject");
1617 hr = CoRevokeClassObject(cookie);
1618 ok_ole_success(hr, "CoRevokeClassObject");
1620 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1621 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1622 ok_ole_success(hr, "CoRegisterClassObject");
1623 hr = CoRevokeClassObject(cookie);
1624 ok_ole_success(hr, "CoRevokeClassObject");
1626 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
1627 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1628 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1629 ok_ole_success(hr, "CoRegisterClassObject");
1630 hr = CoRevokeClassObject(cookie);
1631 ok_ole_success(hr, "CoRevokeClassObject");
1633 /* test whether an object that doesn't support IClassFactory can be
1634 * registered for CLSCTX_LOCAL_SERVER */
1635 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
1636 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1637 ok_ole_success(hr, "CoRegisterClassObject");
1638 hr = CoRevokeClassObject(cookie);
1639 ok_ole_success(hr, "CoRevokeClassObject");
1641 /* test whether registered class becomes invalid when apartment is destroyed */
1642 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1643 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1644 ok_ole_success(hr, "CoRegisterClassObject");
1646 CoUninitialize();
1647 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1649 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
1650 &IID_IClassFactory, (void **)&pcf);
1651 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
1653 /* crashes with at least win9x DCOM! */
1654 if (0)
1655 CoRevokeClassObject(cookie);
1657 /* test that object is accessible */
1658 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER,
1659 REGCLS_MULTIPLEUSE, &cookie);
1660 ok(hr == S_OK, "got 0x%08x\n", hr);
1662 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1663 ok(hr == S_OK, "got 0x%08x\n", hr);
1664 IClassFactory_Release(pcf);
1666 /* context now contains CLSID_WineOOPTest, test if registered one could still be used */
1667 if ((handle = activate_context(actctx_manifest, &ctxcookie)))
1669 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1670 ok(hr == 0x80001234 || broken(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND)) /* winxp */, "Unexpected hr %#x.\n", hr);
1672 deactivate_context(handle, ctxcookie);
1675 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1676 ok(hr == S_OK, "got 0x%08x\n", hr);
1677 IClassFactory_Release(pcf);
1679 hr = CoRevokeClassObject(cookie);
1680 ok(hr == S_OK, "got 0x%08x\n", hr);
1682 CoUninitialize();
1685 static HRESULT get_class_object(CLSCTX clsctx)
1687 HRESULT hr;
1688 IClassFactory *pcf;
1690 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1691 (void **)&pcf);
1693 if (SUCCEEDED(hr))
1694 IClassFactory_Release(pcf);
1696 return hr;
1699 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1701 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1702 HRESULT hr;
1704 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1706 hr = get_class_object(clsctx);
1708 CoUninitialize();
1710 return hr;
1713 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1715 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1716 HRESULT hr;
1717 IClassFactory *pcf;
1718 IMultiQI *pMQI;
1720 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1722 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1723 (void **)&pcf);
1725 if (SUCCEEDED(hr))
1727 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1728 if (SUCCEEDED(hr))
1729 IMultiQI_Release(pMQI);
1730 IClassFactory_Release(pcf);
1733 CoUninitialize();
1735 return hr;
1738 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1740 HRESULT hr;
1741 DWORD cookie;
1743 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1745 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1746 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1748 CoUninitialize();
1750 return hr;
1753 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1755 DWORD cookie = (DWORD_PTR)pv;
1756 HRESULT hr;
1758 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1760 hr = CoRevokeClassObject(cookie);
1762 CoUninitialize();
1764 return hr;
1767 static void test_registered_object_thread_affinity(void)
1769 HRESULT hr;
1770 DWORD cookie;
1771 HANDLE thread;
1772 DWORD tid;
1773 DWORD exitcode;
1775 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1777 /* CLSCTX_INPROC_SERVER */
1779 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1780 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1781 ok_ole_success(hr, "CoRegisterClassObject");
1783 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1784 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1785 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1786 GetExitCodeThread(thread, &exitcode);
1787 hr = exitcode;
1788 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1789 "registered in different thread should return REGDB_E_CLASSNOTREG "
1790 "instead of 0x%08x\n", hr);
1792 hr = get_class_object(CLSCTX_INPROC_SERVER);
1793 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1794 "thread should return S_OK instead of 0x%08x\n", hr);
1796 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1797 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1798 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1799 GetExitCodeThread(thread, &exitcode);
1800 hr = exitcode;
1801 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1803 hr = CoRevokeClassObject(cookie);
1804 ok_ole_success(hr, "CoRevokeClassObject");
1806 /* CLSCTX_LOCAL_SERVER */
1808 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1809 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1810 ok_ole_success(hr, "CoRegisterClassObject");
1812 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1813 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1814 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1816 MSG msg;
1817 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1819 TranslateMessage(&msg);
1820 DispatchMessageA(&msg);
1823 GetExitCodeThread(thread, &exitcode);
1824 hr = exitcode;
1825 ok(hr == S_OK, "CoGetClassObject on local server object "
1826 "registered in different thread should return S_OK "
1827 "instead of 0x%08x\n", hr);
1829 hr = get_class_object(CLSCTX_LOCAL_SERVER);
1830 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1831 "thread should return S_OK instead of 0x%08x\n", hr);
1833 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid);
1834 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1835 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1836 GetExitCodeThread(thread, &exitcode);
1837 hr = exitcode;
1838 ok(hr == RPC_E_WRONG_THREAD || broken(hr == S_OK) /* win8 */, "CoRevokeClassObject called from different "
1839 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1841 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1842 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1843 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1844 GetExitCodeThread(thread, &exitcode);
1845 hr = exitcode;
1846 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1847 "thread should return S_OK instead of 0x%08x\n", hr);
1849 hr = CoRevokeClassObject(cookie);
1850 ok_ole_success(hr, "CoRevokeClassObject");
1852 CoUninitialize();
1855 static DWORD CALLBACK free_libraries_thread(LPVOID p)
1857 CoFreeUnusedLibraries();
1858 return 0;
1861 static inline BOOL is_module_loaded(const char *module)
1863 return GetModuleHandleA(module) != 0;
1866 static void test_CoFreeUnusedLibraries(void)
1868 HRESULT hr;
1869 IUnknown *pUnk;
1870 DWORD tid;
1871 HANDLE thread;
1873 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1875 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1877 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1878 if (hr == REGDB_E_CLASSNOTREG)
1880 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1881 CoUninitialize();
1882 return;
1884 ok_ole_success(hr, "CoCreateInstance");
1886 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1888 ok(pUnk != NULL ||
1889 broken(pUnk == NULL), /* win9x */
1890 "Expected a valid pointer\n");
1891 if (pUnk)
1892 IUnknown_Release(pUnk);
1894 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1896 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1897 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1898 CloseHandle(thread);
1900 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1902 CoFreeUnusedLibraries();
1904 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1906 CoUninitialize();
1909 static void test_CoGetObjectContext(void)
1911 HRESULT hr;
1912 ULONG refs;
1913 IComThreadingInfo *pComThreadingInfo, *threadinginfo2;
1914 IContextCallback *pContextCallback;
1915 IObjContext *pObjContext;
1916 APTTYPE apttype;
1917 THDTYPE thdtype;
1918 GUID id, id2;
1920 if (!pCoGetObjectContext)
1922 win_skip("CoGetObjectContext not present\n");
1923 return;
1926 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1927 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1928 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1930 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1932 test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE);
1934 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1935 ok_ole_success(hr, "CoGetObjectContext");
1937 threadinginfo2 = NULL;
1938 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&threadinginfo2);
1939 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1940 ok(pComThreadingInfo == threadinginfo2, "got different instance\n");
1941 IComThreadingInfo_Release(threadinginfo2);
1943 hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, NULL);
1944 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1946 id = id2 = GUID_NULL;
1947 hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, &id);
1948 ok(hr == S_OK, "got 0x%08x\n", hr);
1950 hr = CoGetCurrentLogicalThreadId(&id2);
1951 ok(IsEqualGUID(&id, &id2), "got %s, expected %s\n", wine_dbgstr_guid(&id), wine_dbgstr_guid(&id2));
1953 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1954 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1955 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1957 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1958 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1959 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1961 refs = IComThreadingInfo_Release(pComThreadingInfo);
1962 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1964 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1965 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1967 refs = IContextCallback_Release(pContextCallback);
1968 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1970 CoUninitialize();
1972 CoInitializeEx(NULL, COINIT_MULTITHREADED);
1974 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1975 ok_ole_success(hr, "CoGetObjectContext");
1977 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1978 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1979 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1981 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1982 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1983 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1985 refs = IComThreadingInfo_Release(pComThreadingInfo);
1986 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1988 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1989 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1991 refs = IContextCallback_Release(pContextCallback);
1992 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1994 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1995 ok_ole_success(hr, "CoGetObjectContext");
1997 refs = IObjContext_Release(pObjContext);
1998 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
2000 CoUninitialize();
2003 typedef struct {
2004 IUnknown IUnknown_iface;
2005 LONG refs;
2006 } Test_CallContext;
2008 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
2010 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
2013 static HRESULT WINAPI Test_CallContext_QueryInterface(
2014 IUnknown *iface,
2015 REFIID riid,
2016 LPVOID *ppvObj)
2018 if (ppvObj == NULL) return E_POINTER;
2020 if (IsEqualGUID(riid, &IID_IUnknown))
2022 *ppvObj = iface;
2023 IUnknown_AddRef(iface);
2024 return S_OK;
2027 *ppvObj = NULL;
2028 return E_NOINTERFACE;
2031 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
2033 Test_CallContext *This = impl_from_IUnknown(iface);
2034 return InterlockedIncrement(&This->refs);
2037 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
2039 Test_CallContext *This = impl_from_IUnknown(iface);
2040 ULONG refs = InterlockedDecrement(&This->refs);
2041 if (!refs)
2042 HeapFree(GetProcessHeap(), 0, This);
2043 return refs;
2046 static const IUnknownVtbl TestCallContext_Vtbl =
2048 Test_CallContext_QueryInterface,
2049 Test_CallContext_AddRef,
2050 Test_CallContext_Release
2053 static void test_CoGetCallContext(void)
2055 HRESULT hr;
2056 ULONG refs;
2057 IUnknown *pUnk;
2058 Test_CallContext *test_object;
2060 if (!pCoSwitchCallContext)
2062 skip("CoSwitchCallContext not present\n");
2063 return;
2066 CoInitialize(NULL);
2068 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
2069 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
2070 test_object->refs = 1;
2072 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
2073 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
2075 pUnk = (IUnknown*)0xdeadbeef;
2076 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
2077 ok_ole_success(hr, "CoSwitchCallContext");
2078 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
2079 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
2080 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
2081 IUnknown_Release(&test_object->IUnknown_iface);
2083 pUnk = (IUnknown*)0xdeadbeef;
2084 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
2085 ok_ole_success(hr, "CoGetCallContext");
2086 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
2087 &test_object->IUnknown_iface, pUnk);
2088 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
2089 ok(refs == 3, "Expected refcount 3, got %d\n", refs);
2090 IUnknown_Release(&test_object->IUnknown_iface);
2091 IUnknown_Release(pUnk);
2093 pUnk = (IUnknown*)0xdeadbeef;
2094 hr = pCoSwitchCallContext(NULL, &pUnk);
2095 ok_ole_success(hr, "CoSwitchCallContext");
2096 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
2097 &test_object->IUnknown_iface, pUnk);
2098 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
2099 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
2100 IUnknown_Release(&test_object->IUnknown_iface);
2102 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
2103 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
2105 IUnknown_Release(&test_object->IUnknown_iface);
2107 CoUninitialize();
2110 static void test_CoGetContextToken(void)
2112 HRESULT hr;
2113 ULONG refs;
2114 ULONG_PTR token, token2;
2115 IObjContext *ctx;
2117 if (!pCoGetContextToken)
2119 win_skip("CoGetContextToken not present\n");
2120 return;
2123 token = 0xdeadbeef;
2124 hr = pCoGetContextToken(&token);
2125 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
2126 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
2128 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
2130 CoInitialize(NULL);
2132 test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE);
2134 hr = pCoGetContextToken(NULL);
2135 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
2137 token = 0;
2138 hr = pCoGetContextToken(&token);
2139 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2140 ok(token, "Expected token != 0\n");
2142 token2 = 0;
2143 hr = pCoGetContextToken(&token2);
2144 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2145 ok(token2 == token, "got different token\n");
2147 refs = IUnknown_AddRef((IUnknown *)token);
2148 ok(refs == 1, "Expected 1, got %u\n", refs);
2150 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
2151 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2152 ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
2154 refs = IObjContext_AddRef(ctx);
2155 ok(refs == 3, "Expected 3, got %u\n", refs);
2157 refs = IObjContext_Release(ctx);
2158 ok(refs == 2, "Expected 2, got %u\n", refs);
2160 refs = IUnknown_Release((IUnknown *)token);
2161 ok(refs == 1, "Expected 1, got %u\n", refs);
2163 /* CoGetContextToken does not add a reference */
2164 token = 0;
2165 hr = pCoGetContextToken(&token);
2166 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2167 ok(token, "Expected token != 0\n");
2168 ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
2170 refs = IObjContext_AddRef(ctx);
2171 ok(refs == 2, "Expected 1, got %u\n", refs);
2173 refs = IObjContext_Release(ctx);
2174 ok(refs == 1, "Expected 0, got %u\n", refs);
2176 refs = IObjContext_Release(ctx);
2177 ok(refs == 0, "Expected 0, got %u\n", refs);
2179 CoUninitialize();
2182 static void test_TreatAsClass(void)
2184 HRESULT hr;
2185 CLSID out;
2186 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
2187 static const char deadbeefA[] = "{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}";
2188 IInternetProtocol *pIP = NULL;
2189 HKEY clsidkey, deadbeefkey;
2190 LONG lr;
2192 hr = CoGetTreatAsClass(&deadbeef,&out);
2193 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
2194 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
2196 hr = CoGetTreatAsClass(NULL, &out);
2197 ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr);
2198 ok(IsEqualGUID(&out, &deadbeef), "expected no change to the clsid\n");
2200 hr = CoGetTreatAsClass(&deadbeef, NULL);
2201 ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr);
2203 lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &clsidkey);
2204 ok(!lr, "Couldn't open CLSID key, error %d\n", lr);
2206 lr = RegCreateKeyExA(clsidkey, deadbeefA, 0, NULL, 0, KEY_WRITE, NULL, &deadbeefkey, NULL);
2207 if (lr) {
2208 win_skip("CoGetTreatAsClass() tests will be skipped (failed to create a test key, error %d)\n", lr);
2209 RegCloseKey(clsidkey);
2210 return;
2213 hr = CoTreatAsClass(&deadbeef, &deadbeef);
2214 ok(hr == REGDB_E_WRITEREGDB, "CoTreatAsClass gave wrong error: %08x\n", hr);
2216 hr = CoTreatAsClass(&deadbeef, &CLSID_FileProtocol);
2217 if(hr == REGDB_E_WRITEREGDB){
2218 win_skip("Insufficient privileges to use CoTreatAsClass\n");
2219 goto exit;
2221 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
2223 hr = CoGetTreatAsClass(&deadbeef, &out);
2224 ok(hr == S_OK, "CoGetTreatAsClass failed: %08x\n",hr);
2225 ok(IsEqualGUID(&out, &CLSID_FileProtocol), "expected to get substituted clsid\n");
2227 OleInitialize(NULL);
2229 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2230 if(hr == REGDB_E_CLASSNOTREG)
2232 win_skip("IE not installed so can't test CoCreateInstance\n");
2233 goto exit;
2236 ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
2237 if(pIP){
2238 IInternetProtocol_Release(pIP);
2239 pIP = NULL;
2242 if (pCoCreateInstanceFromApp)
2244 MULTI_QI mqi = { 0 };
2246 mqi.pIID = &IID_IInternetProtocol;
2247 hr = pCoCreateInstanceFromApp(&deadbeef, NULL, CLSCTX_INPROC_SERVER, NULL, 1, &mqi);
2248 ok(hr == REGDB_E_CLASSNOTREG, "Unexpected hr %#x.\n", hr);
2250 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER | CLSCTX_APPCONTAINER, &IID_IInternetProtocol,
2251 (void **)&pIP);
2252 ok(hr == REGDB_E_CLASSNOTREG, "Unexpected hr %#x.\n", hr);
2254 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2255 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2256 IUnknown_Release(pIP);
2259 hr = CoTreatAsClass(&deadbeef, &CLSID_NULL);
2260 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
2262 hr = CoGetTreatAsClass(&deadbeef, &out);
2263 ok(hr == S_FALSE, "expected S_FALSE got %08x\n", hr);
2264 ok(IsEqualGUID(&out, &deadbeef), "expected to get same clsid back\n");
2266 /* bizarrely, native's CoTreatAsClass takes some time to take effect in CoCreateInstance */
2267 Sleep(200);
2269 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2270 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance gave wrong error: %08x\n", hr);
2272 if(pIP)
2273 IInternetProtocol_Release(pIP);
2275 exit:
2276 OleUninitialize();
2277 RegCloseKey(deadbeefkey);
2278 RegDeleteKeyA(clsidkey, deadbeefA);
2279 RegCloseKey(clsidkey);
2282 static void test_CoInitializeEx(void)
2284 HRESULT hr;
2286 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2287 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2289 /* Calling OleInitialize for the first time should yield S_OK even with
2290 * apartment already initialized by previous CoInitialize(Ex) calls. */
2291 hr = OleInitialize(NULL);
2292 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
2294 /* Subsequent calls to OleInitialize should return S_FALSE */
2295 hr = OleInitialize(NULL);
2296 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
2298 /* Cleanup */
2299 CoUninitialize();
2300 OleUninitialize();
2301 OleUninitialize();
2304 static void test_OleInitialize_InitCounting(void)
2306 HRESULT hr;
2307 IUnknown *pUnk;
2308 REFCLSID rclsid = &CLSID_InternetZoneManager;
2310 /* 1. OleInitialize fails but OleUninitialize is still called: apartment stays initialized */
2311 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
2312 ok(hr == S_OK, "CoInitializeEx(COINIT_MULTITHREADED) failed with error 0x%08x\n", hr);
2314 hr = OleInitialize(NULL);
2315 ok(hr == RPC_E_CHANGED_MODE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", RPC_E_CHANGED_MODE, hr);
2316 OleUninitialize();
2318 pUnk = (IUnknown *)0xdeadbeef;
2319 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2320 ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2321 if (pUnk) IUnknown_Release(pUnk);
2323 CoUninitialize();
2325 /* 2. Extra multiple OleUninitialize: apartment stays initialized until CoUninitialize */
2326 hr = CoInitialize(NULL);
2327 ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
2329 hr = OleInitialize(NULL);
2330 ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2331 OleUninitialize();
2332 OleUninitialize();
2333 OleUninitialize();
2335 pUnk = (IUnknown *)0xdeadbeef;
2336 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2337 ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2338 if (pUnk) IUnknown_Release(pUnk);
2340 CoUninitialize();
2342 pUnk = (IUnknown *)0xdeadbeef;
2343 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2344 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
2345 if (pUnk) IUnknown_Release(pUnk);
2347 /* 3. CoUninitialize does not formally deinit Ole */
2348 hr = CoInitialize(NULL);
2349 ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
2351 hr = OleInitialize(NULL);
2352 ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2354 CoUninitialize();
2355 CoUninitialize();
2357 pUnk = (IUnknown *)0xdeadbeef;
2358 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2359 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
2360 /* COM is not initialized anymore */
2361 if (pUnk) IUnknown_Release(pUnk);
2363 hr = OleInitialize(NULL);
2364 ok(hr == S_FALSE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_FALSE, hr);
2365 /* ... but native OleInit returns S_FALSE as if Ole is considered initialized */
2367 OleUninitialize();
2371 static void test_OleRegGetMiscStatus(void)
2373 ULONG_PTR cookie;
2374 HANDLE handle;
2375 DWORD status;
2376 HRESULT hr;
2378 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, NULL);
2379 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2381 status = 0xdeadbeef;
2382 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2383 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
2384 ok(status == 0, "got 0x%08x\n", status);
2386 status = -1;
2387 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2388 ok(hr == S_OK, "got 0x%08x\n", hr);
2389 ok(status == 0, "got 0x%08x\n", status);
2391 if ((handle = activate_context(actctx_manifest, &cookie)))
2393 status = 0;
2394 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2395 ok(hr == S_OK, "got 0x%08x\n", hr);
2396 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2398 /* context data takes precedence over registration info */
2399 status = 0;
2400 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2401 ok(hr == S_OK, "got 0x%08x\n", hr);
2402 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2404 /* there's no such attribute in context */
2405 status = -1;
2406 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status);
2407 ok(hr == S_OK, "got 0x%08x\n", hr);
2408 ok(status == 0, "got 0x%08x\n", status);
2410 deactivate_context(handle, cookie);
2414 static void test_OleRegGetUserType(void)
2416 static const WCHAR stdfont_usertypeW[] = {'S','t','a','n','d','a','r','d',' ','F','o','n','t',0};
2417 static const WCHAR stdfont2_usertypeW[] = {'C','L','S','I','D','_','S','t','d','F','o','n','t',0};
2418 static const WCHAR clsidkeyW[] = {'C','L','S','I','D',0};
2419 static const WCHAR defvalueW[] = {'D','e','f','a','u','l','t',' ','N','a','m','e',0};
2420 static const WCHAR auxvalue0W[] = {'A','u','x',' ','N','a','m','e',' ','0',0};
2421 static const WCHAR auxvalue2W[] = {'A','u','x',' ','N','a','m','e',' ','2',0};
2422 static const WCHAR auxvalue3W[] = {'A','u','x',' ','N','a','m','e',' ','3',0};
2423 static const WCHAR auxvalue4W[] = {'A','u','x',' ','N','a','m','e',' ','4',0};
2425 static const char auxvalues[][16] = {
2426 "Aux Name 0",
2427 "Aux Name 1",
2428 "Aux Name 2",
2429 "Aux Name 3",
2430 "Aux Name 4"
2433 HKEY clsidhkey, hkey, auxhkey, classkey;
2434 DWORD form, ret, disposition;
2435 WCHAR clsidW[39];
2436 ULONG_PTR cookie;
2437 HANDLE handle;
2438 HRESULT hr;
2439 WCHAR *str;
2440 int i;
2442 for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) {
2443 hr = OleRegGetUserType(&CLSID_Testclass, form, NULL);
2444 ok(hr == E_INVALIDARG, "form %u: got 0x%08x\n", form, hr);
2446 str = (void*)0xdeadbeef;
2447 hr = OleRegGetUserType(&CLSID_Testclass, form, &str);
2448 ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr);
2449 ok(str == NULL, "form %u: got %p\n", form, str);
2451 /* same string returned for StdFont for all form types */
2452 str = NULL;
2453 hr = OleRegGetUserType(&CLSID_StdFont, form, &str);
2454 ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr);
2455 ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */,
2456 "form %u, got %s\n", form, wine_dbgstr_w(str));
2457 CoTaskMemFree(str);
2460 if ((handle = activate_context(actctx_manifest, &cookie)))
2462 for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) {
2463 str = (void*)0xdeadbeef;
2464 hr = OleRegGetUserType(&CLSID_Testclass, form, &str);
2465 ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr);
2466 ok(str == NULL, "form %u: got %s\n", form, wine_dbgstr_w(str));
2468 /* same string returned for StdFont for all form types */
2469 str = NULL;
2470 hr = OleRegGetUserType(&CLSID_StdFont, form, &str);
2471 ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr);
2472 ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */,
2473 "form %u, got %s\n", form, wine_dbgstr_w(str));
2474 CoTaskMemFree(str);
2477 deactivate_context(handle, cookie);
2480 /* test using registered CLSID */
2481 StringFromGUID2(&CLSID_non_existent, clsidW, ARRAY_SIZE(clsidW));
2483 ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsidkeyW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &clsidhkey, &disposition);
2484 if (!ret)
2486 ret = RegCreateKeyExW(clsidhkey, clsidW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &classkey, NULL);
2487 if (ret)
2488 RegCloseKey(clsidhkey);
2491 if (ret == ERROR_ACCESS_DENIED)
2493 win_skip("Failed to create test key, skipping some of OleRegGetUserType() tests.\n");
2494 return;
2497 ok(!ret, "failed to create a key, error %d\n", ret);
2499 ret = RegSetValueExW(classkey, NULL, 0, REG_SZ, (const BYTE*)defvalueW, sizeof(defvalueW));
2500 ok(!ret, "got error %d\n", ret);
2502 ret = RegCreateKeyExA(classkey, "AuxUserType", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &auxhkey, NULL);
2503 ok(!ret, "got error %d\n", ret);
2505 /* populate AuxUserType */
2506 for (i = 0; i <= 4; i++) {
2507 char name[16];
2509 sprintf(name, "AuxUserType\\%d", i);
2510 ret = RegCreateKeyExA(classkey, name, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2511 ok(!ret, "got error %d\n", ret);
2513 ret = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE*)auxvalues[i], strlen(auxvalues[i]));
2514 ok(!ret, "got error %d\n", ret);
2515 RegCloseKey(hkey);
2518 str = NULL;
2519 hr = OleRegGetUserType(&CLSID_non_existent, 0, &str);
2520 ok(hr == S_OK, "got 0x%08x\n", hr);
2521 ok(!lstrcmpW(str, auxvalue0W), "got %s\n", wine_dbgstr_w(str));
2522 CoTaskMemFree(str);
2524 str = NULL;
2525 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_FULL, &str);
2526 ok(hr == S_OK, "got 0x%08x\n", hr);
2527 ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str));
2528 CoTaskMemFree(str);
2530 str = NULL;
2531 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_SHORT, &str);
2532 ok(hr == S_OK, "got 0x%08x\n", hr);
2533 ok(!lstrcmpW(str, auxvalue2W), "got %s\n", wine_dbgstr_w(str));
2534 CoTaskMemFree(str);
2536 str = NULL;
2537 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME, &str);
2538 ok(hr == S_OK, "got 0x%08x\n", hr);
2539 ok(!lstrcmpW(str, auxvalue3W), "got %s\n", wine_dbgstr_w(str));
2540 CoTaskMemFree(str);
2542 str = NULL;
2543 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+1, &str);
2544 ok(hr == S_OK, "got 0x%08x\n", hr);
2545 ok(!lstrcmpW(str, auxvalue4W), "got %s\n", wine_dbgstr_w(str));
2546 CoTaskMemFree(str);
2548 str = NULL;
2549 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+2, &str);
2550 ok(hr == S_OK, "got 0x%08x\n", hr);
2551 ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str));
2552 CoTaskMemFree(str);
2554 /* registry cleanup */
2555 for (i = 0; i <= 4; i++)
2557 char name[2];
2558 sprintf(name, "%d", i);
2559 RegDeleteKeyA(auxhkey, name);
2561 RegCloseKey(auxhkey);
2562 RegDeleteKeyA(classkey, "AuxUserType");
2563 RegCloseKey(classkey);
2564 RegDeleteKeyW(clsidhkey, clsidW);
2565 RegCloseKey(clsidhkey);
2566 if (disposition == REG_CREATED_NEW_KEY)
2567 RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID");
2570 static void test_CoCreateGuid(void)
2572 HRESULT hr;
2574 hr = CoCreateGuid(NULL);
2575 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2578 static void CALLBACK apc_test_proc(ULONG_PTR param)
2580 /* nothing */
2583 static DWORD CALLBACK release_semaphore_thread( LPVOID arg )
2585 HANDLE handle = arg;
2586 if (WaitForSingleObject(handle, 200) == WAIT_TIMEOUT)
2587 ReleaseSemaphore(handle, 1, NULL);
2588 return 0;
2591 static DWORD CALLBACK send_message_thread(LPVOID arg)
2593 HWND hWnd = arg;
2594 SendMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2595 return 0;
2598 static DWORD CALLBACK send_and_post_user_message_thread(void *arg)
2600 HWND hwnd = arg;
2601 Sleep(30);
2602 SendMessageA(hwnd, WM_USER, 0, 0);
2603 PostMessageA(hwnd, WM_USER, 0, 0);
2604 return 0;
2607 static DWORD CALLBACK post_message_thread(LPVOID arg)
2609 HWND hWnd = arg;
2610 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2611 return 0;
2614 static const char cls_name[] = "cowait_test_class";
2616 static UINT cowait_msgs[100], cowait_msgs_first, cowait_msgs_last;
2618 static void cowait_msgs_reset(void)
2620 cowait_msgs_first = cowait_msgs_last = 0;
2623 #define cowait_msgs_expect_empty() _cowait_msgs_expect_empty(__LINE__)
2624 static void _cowait_msgs_expect_empty(unsigned line)
2626 while(cowait_msgs_first < cowait_msgs_last) {
2627 ok_(__FILE__,line)(0, "unexpected message %u\n", cowait_msgs[cowait_msgs_first]);
2628 cowait_msgs_first++;
2630 cowait_msgs_reset();
2633 #define cowait_msgs_expect_notified(a) _cowait_msgs_expect_notified(__LINE__,a)
2634 static void _cowait_msgs_expect_notified(unsigned line, UINT expected_msg)
2636 if(cowait_msgs_first == cowait_msgs_last) {
2637 ok_(__FILE__,line)(0, "expected message %u, received none\n", expected_msg);
2638 }else {
2639 ok_(__FILE__,line)(cowait_msgs[cowait_msgs_first] == expected_msg,
2640 "expected message %u, received %u \n",
2641 expected_msg, cowait_msgs[cowait_msgs_first]);
2642 cowait_msgs_first++;
2646 #define cowait_msgs_expect_queued(a,b) _cowait_msgs_expect_queued(__LINE__,a,b)
2647 static void _cowait_msgs_expect_queued(unsigned line, HWND hwnd, UINT expected_msg)
2649 MSG msg;
2650 BOOL success;
2652 success = PeekMessageA(&msg, hwnd, expected_msg, expected_msg, PM_REMOVE);
2653 ok_(__FILE__,line)(success, "PeekMessageA failed: %u\n", GetLastError());
2654 if(success)
2655 ok_(__FILE__,line)(msg.message == expected_msg, "unexpected message %u, expected %u\n",
2656 msg.message, expected_msg);
2659 static void flush_messages(void)
2661 MSG msg;
2662 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ));
2665 static LRESULT CALLBACK cowait_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
2667 if(cowait_msgs_last < ARRAY_SIZE(cowait_msgs))
2668 cowait_msgs[cowait_msgs_last++] = msg;
2669 if(msg == WM_DDE_FIRST)
2670 return 6;
2671 return DefWindowProcA(hwnd, msg, wparam, lparam);
2674 static DWORD CALLBACK cowait_unmarshal_thread(void *arg)
2676 IStream *stream = arg;
2677 IEnumOLEVERB *enum_verb;
2678 LARGE_INTEGER zero;
2679 IUnknown *unk;
2680 HRESULT hr;
2682 CoInitialize(NULL);
2684 zero.QuadPart = 0;
2685 hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2686 ok(hr == S_OK, "Seek failed: %08x\n", hr);
2688 hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk);
2689 ok(hr == S_OK, "CoUnmarshalInterface failed: %08x\n", hr);
2691 hr = IUnknown_QueryInterface(unk, &IID_IEnumOLEVERB, (void**)&enum_verb);
2692 ok(hr == S_OK, "QueryInterface failed: %08x\n", hr);
2694 IEnumOLEVERB_Release(enum_verb);
2695 IUnknown_Release(unk);
2697 CoUninitialize();
2698 return 0;
2701 static DWORD CALLBACK test_CoWaitForMultipleHandles_thread(LPVOID arg)
2703 HANDLE *handles = arg, event, thread;
2704 IStream *stream;
2705 BOOL success;
2706 DWORD index, tid;
2707 HRESULT hr;
2708 HWND hWnd;
2709 UINT uMSG = 0xc065;
2710 MSG msg;
2711 int ret;
2713 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2714 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2716 hWnd = CreateWindowExA(0, cls_name, "Test (thread)", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2717 ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
2719 index = 0xdeadbeef;
2720 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2721 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2722 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2723 ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index);
2724 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2725 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2727 index = 0xdeadbeef;
2728 PostMessageA(hWnd, WM_USER, 0, 0);
2729 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2730 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2731 ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index);
2732 success = PeekMessageA(&msg, hWnd, WM_USER, WM_USER, PM_REMOVE);
2733 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2735 /* Even if CoWaitForMultipleHandles does not pump a message it peeks
2736 * at ALL of them */
2737 index = 0xdeadbeef;
2738 PostMessageA(NULL, uMSG, 0, 0);
2740 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2741 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2742 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2744 /* Make sure message was peeked at */
2745 ret = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE);
2746 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
2748 /* But not pumped */
2749 success = PeekMessageA(&msg, NULL, uMSG, uMSG, PM_REMOVE);
2750 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2752 DestroyWindow(hWnd);
2753 CoUninitialize();
2755 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2756 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2758 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2759 ok(hr == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hr);
2761 hr = CoMarshalInterface(stream, &IID_IUnknown, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2762 ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
2764 event = CreateEventW(NULL, TRUE, FALSE, NULL);
2766 PostQuitMessage(66);
2767 PostThreadMessageW(GetCurrentThreadId(), WM_QUIT, 0, 0);
2769 hr = CoRegisterMessageFilter(&MessageFilter, NULL);
2770 ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr);
2772 thread = CreateThread(NULL, 0, cowait_unmarshal_thread, stream, 0, &tid);
2773 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2774 hr = CoWaitForMultipleHandles(0, 50, 1, &event, &index);
2775 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2776 hr = CoWaitForMultipleHandles(0, 200, 1, &thread, &index);
2777 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2778 ok(index == WAIT_OBJECT_0, "cowait_unmarshal_thread didn't finish\n");
2779 CloseHandle(thread);
2781 hr = CoRegisterMessageFilter(NULL, NULL);
2782 ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr);
2784 IStream_Release(stream);
2786 CloseHandle(event);
2787 CoUninitialize();
2788 return 0;
2791 static void test_CoWaitForMultipleHandles(void)
2793 HANDLE handles[2], thread;
2794 DWORD index, tid;
2795 WNDCLASSEXA wc;
2796 BOOL success;
2797 HRESULT hr;
2798 HWND hWnd;
2799 MSG msg;
2801 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2802 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2804 memset(&wc, 0, sizeof(wc));
2805 wc.cbSize = sizeof(wc);
2806 wc.style = CS_VREDRAW | CS_HREDRAW;
2807 wc.hInstance = GetModuleHandleA(0);
2808 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2809 wc.hbrBackground = NULL;
2810 wc.lpszClassName = cls_name;
2811 wc.lpfnWndProc = cowait_window_proc;
2812 success = RegisterClassExA(&wc) != 0;
2813 ok(success, "RegisterClassExA failed %u\n", GetLastError());
2815 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2816 ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
2817 handles[0] = CreateSemaphoreA(NULL, 1, 1, NULL);
2818 ok(handles[0] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2819 handles[1] = CreateSemaphoreA(NULL, 1, 1, NULL);
2820 ok(handles[1] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2822 /* test without flags */
2824 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2825 hr = CoWaitForMultipleHandles(0, 50, 0, handles, NULL);
2826 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2827 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2828 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2830 index = 0xdeadbeef;
2831 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2832 hr = CoWaitForMultipleHandles(0, 50, 0, NULL, &index);
2833 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2834 ok(index == 0, "expected index 0, got %u\n", index);
2835 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2836 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2838 index = 0xdeadbeef;
2839 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2840 hr = CoWaitForMultipleHandles(0, 50, 0, handles, &index);
2841 ok(hr == RPC_E_NO_SYNC, "expected RPC_E_NO_SYNC, got 0x%08x\n", hr);
2842 ok(index == 0, "expected index 0, got %u\n", index);
2843 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2844 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2846 index = 0xdeadbeef;
2847 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2848 hr = CoWaitForMultipleHandles(0, 50, 1, handles, &index);
2849 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2850 ok(index == 0, "expected index 0, got %u\n", index);
2851 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2852 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2854 index = 0xdeadbeef;
2855 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2856 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2857 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2858 ok(index == 1, "expected index 1, got %u\n", index);
2859 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2860 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2862 index = 0xdeadbeef;
2863 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2864 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2865 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2866 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2867 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2868 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2870 /* test PostMessageA/SendMessageA from a different thread */
2872 index = 0xdeadbeef;
2873 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2874 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2875 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2876 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2877 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2878 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2879 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2880 index = WaitForSingleObject(thread, 200);
2881 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2882 CloseHandle(thread);
2884 index = 0xdeadbeef;
2885 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2886 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2887 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2888 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2889 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2890 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2891 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2892 index = WaitForSingleObject(thread, 200);
2893 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2894 CloseHandle(thread);
2896 ReleaseSemaphore(handles[0], 1, NULL);
2897 ReleaseSemaphore(handles[1], 1, NULL);
2899 /* test with COWAIT_WAITALL */
2901 index = 0xdeadbeef;
2902 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2903 hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 50, 2, handles, &index);
2904 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2905 ok(index == 0, "expected index 0, got %u\n", index);
2906 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2907 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2909 index = 0xdeadbeef;
2910 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2911 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2912 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2913 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2914 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2915 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2917 ReleaseSemaphore(handles[0], 1, NULL);
2918 ReleaseSemaphore(handles[1], 1, NULL);
2920 /* test with COWAIT_ALERTABLE */
2922 index = 0xdeadbeef;
2923 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2924 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 1, handles, &index);
2925 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2926 ok(index == 0, "expected index 0, got %u\n", index);
2927 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2928 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2930 index = 0xdeadbeef;
2931 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2932 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2933 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2934 ok(index == 1, "expected index 1, got %u\n", index);
2935 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2936 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2938 index = 0xdeadbeef;
2939 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2940 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2941 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2942 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2943 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2944 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2946 index = 0xdeadbeef;
2947 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2948 success = QueueUserAPC(apc_test_proc, GetCurrentThread(), 0);
2949 ok(success, "QueueUserAPC failed %u\n", GetLastError());
2950 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2951 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2952 ok(index == WAIT_IO_COMPLETION, "expected index WAIT_IO_COMPLETION, got %u\n", index);
2953 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2954 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2956 /* test with COWAIT_INPUTAVAILABLE (semaphores are still locked) */
2958 index = 0xdeadbeef;
2959 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2960 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2961 ok(success, "PeekMessageA returned FALSE\n");
2962 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2963 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2964 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2965 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2966 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2968 index = 0xdeadbeef;
2969 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2970 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2971 ok(success, "PeekMessageA returned FALSE\n");
2972 thread = CreateThread(NULL, 0, release_semaphore_thread, handles[1], 0, &tid);
2973 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2974 hr = CoWaitForMultipleHandles(COWAIT_INPUTAVAILABLE, 50, 2, handles, &index);
2975 ok(hr == RPC_S_CALLPENDING || broken(hr == E_INVALIDARG) || broken(hr == S_OK) /* Win 8 */,
2976 "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2977 if (hr != S_OK) ReleaseSemaphore(handles[1], 1, NULL);
2978 ok(index == 0 || broken(index == 1) /* Win 8 */, "expected index 0, got %u\n", index);
2979 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2980 ok(!success || broken(success && hr == E_INVALIDARG),
2981 "CoWaitForMultipleHandles didn't pump any messages\n");
2982 index = WaitForSingleObject(thread, 200);
2983 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2984 CloseHandle(thread);
2986 cowait_msgs_reset();
2987 PostMessageA(hWnd, 0, 0, 0);
2988 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2989 PostMessageA(hWnd, WM_USER+1, 0, 0);
2990 PostMessageA(hWnd, WM_DDE_FIRST+1, 0, 0);
2991 thread = CreateThread(NULL, 0, send_and_post_user_message_thread, hWnd, 0, &tid);
2992 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2994 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2995 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2997 cowait_msgs_expect_notified(WM_DDE_FIRST);
2998 cowait_msgs_expect_notified(WM_DDE_FIRST+1);
2999 cowait_msgs_expect_notified(WM_USER);
3000 cowait_msgs_expect_empty();
3001 cowait_msgs_expect_queued(hWnd, WM_USER);
3002 cowait_msgs_expect_queued(hWnd, WM_USER+1);
3003 flush_messages();
3005 index = WaitForSingleObject(thread, 200);
3006 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3007 CloseHandle(thread);
3009 /* test behaviour of WM_QUIT (semaphores are still locked) */
3011 PostMessageA(hWnd, WM_QUIT, 40, 0);
3012 memset(&msg, 0, sizeof(msg));
3013 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
3014 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
3015 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
3016 ok(msg.wParam == 40, "expected msg.wParam = 40, got %lu\n", msg.wParam);
3017 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
3018 ok(!success, "PeekMessageA succeeded\n");
3020 cowait_msgs_reset();
3021 PostMessageA(hWnd, WM_QUIT, 40, 0);
3022 PostMessageA(hWnd, 0, 0, 0);
3023 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3024 PostMessageA(hWnd, WM_USER+1, 0, 0);
3025 PostMessageA(hWnd, WM_DDE_FIRST+1, 0, 0);
3026 thread = CreateThread(NULL, 0, send_and_post_user_message_thread, hWnd, 0, &tid);
3027 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
3029 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3030 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
3032 cowait_msgs_expect_notified(WM_DDE_FIRST);
3033 cowait_msgs_expect_notified(WM_DDE_FIRST+1);
3034 cowait_msgs_expect_notified(WM_USER);
3035 cowait_msgs_expect_empty();
3036 cowait_msgs_expect_queued(hWnd, WM_USER);
3037 flush_messages();
3039 index = WaitForSingleObject(thread, 200);
3040 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3041 CloseHandle(thread);
3043 index = 0xdeadbeef;
3044 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3045 PostMessageA(hWnd, WM_QUIT, 41, 0);
3046 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
3047 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
3048 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3049 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
3050 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
3051 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3052 todo_wine
3053 ok(success || broken(!success) /* Win 2000/XP/8 */, "PeekMessageA failed, error %u\n", GetLastError());
3054 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3055 ok(!success, "PeekMessageA succeeded\n");
3056 memset(&msg, 0, sizeof(msg));
3057 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
3058 todo_wine
3059 ok(!success || broken(success) /* Win 2000/XP/8 */, "PeekMessageA succeeded\n");
3060 if (success)
3062 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
3063 ok(msg.wParam == 41, "expected msg.wParam = 41, got %lu\n", msg.wParam);
3065 index = WaitForSingleObject(thread, 200);
3066 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3067 CloseHandle(thread);
3069 index = 0xdeadbeef;
3070 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3071 PostMessageA(hWnd, WM_QUIT, 42, 0);
3072 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
3073 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
3074 hr = CoWaitForMultipleHandles(0, 500, 2, handles, &index);
3075 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
3076 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
3077 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3078 ok(!success, "CoWaitForMultipleHandles didn't pump all WM_DDE_FIRST messages\n");
3079 memset(&msg, 0, sizeof(msg));
3080 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
3081 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
3082 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
3083 ok(msg.wParam == 42, "expected msg.wParam = 42, got %lu\n", msg.wParam);
3084 index = WaitForSingleObject(thread, 200);
3085 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3086 CloseHandle(thread);
3088 PostQuitMessage(43);
3089 memset(&msg, 0, sizeof(msg));
3090 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
3091 ok(success || broken(!success) /* Win 8 */, "PeekMessageA failed, error %u\n", GetLastError());
3092 if (!success)
3093 win_skip("PostQuitMessage didn't queue a WM_QUIT message, skipping tests\n");
3094 else
3096 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
3097 ok(msg.wParam == 43, "expected msg.wParam = 43, got %lu\n", msg.wParam);
3098 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
3099 ok(!success, "PeekMessageA succeeded\n");
3101 index = 0xdeadbeef;
3102 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3103 PostQuitMessage(44);
3104 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
3105 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
3106 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3107 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
3108 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
3109 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3110 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
3111 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3112 ok(!success, "PeekMessageA succeeded\n");
3113 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
3114 ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n");
3115 index = WaitForSingleObject(thread, 200);
3116 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3117 CloseHandle(thread);
3119 index = 0xdeadbeef;
3120 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3121 PostQuitMessage(45);
3122 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
3123 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
3124 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3125 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
3126 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
3127 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3128 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
3129 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3130 ok(!success, "PeekMessageA succeeded\n");
3131 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
3132 ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n");
3133 index = WaitForSingleObject(thread, 200);
3134 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3135 CloseHandle(thread);
3138 /* test message pumping when CoWaitForMultipleHandles is called from non main apartment thread */
3139 thread = CreateThread(NULL, 0, test_CoWaitForMultipleHandles_thread, handles, 0, &tid);
3140 index = WaitForSingleObject(thread, 5000);
3141 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3142 CloseHandle(thread);
3144 CoUninitialize();
3146 /* If COM was not initialized, messages are neither pumped nor peeked at */
3147 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3148 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3149 ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr);
3150 success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE);
3151 ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success);
3152 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3153 ok(success, "PeekMessage failed: %u\n", GetLastError());
3155 /* same in an MTA */
3156 CoInitializeEx(NULL, COINIT_MULTITHREADED);
3158 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3159 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3160 ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr);
3161 success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE);
3162 ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success);
3163 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3164 ok(success, "PeekMessage failed: %u\n", GetLastError());
3166 CoUninitialize();
3168 CloseHandle(handles[0]);
3169 CloseHandle(handles[1]);
3170 DestroyWindow(hWnd);
3172 success = UnregisterClassA(cls_name, GetModuleHandleA(0));
3173 ok(success, "UnregisterClass failed %u\n", GetLastError());
3176 static void test_CoGetMalloc(void)
3178 IMalloc *imalloc;
3179 SIZE_T size;
3180 HRESULT hr;
3181 char *ptr;
3182 int ret;
3184 if (0) /* crashes on native */
3185 hr = CoGetMalloc(0, NULL);
3187 imalloc = (void*)0xdeadbeef;
3188 hr = CoGetMalloc(0, &imalloc);
3189 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3190 ok(imalloc == NULL, "got %p\n", imalloc);
3192 imalloc = (void*)0xdeadbeef;
3193 hr = CoGetMalloc(MEMCTX_SHARED, &imalloc);
3194 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3195 ok(imalloc == NULL, "got %p\n", imalloc);
3197 imalloc = (void*)0xdeadbeef;
3198 hr = CoGetMalloc(MEMCTX_MACSYSTEM, &imalloc);
3199 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3200 ok(imalloc == NULL, "got %p\n", imalloc);
3202 imalloc = (void*)0xdeadbeef;
3203 hr = CoGetMalloc(MEMCTX_UNKNOWN, &imalloc);
3204 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3205 ok(imalloc == NULL, "got %p\n", imalloc);
3207 imalloc = (void*)0xdeadbeef;
3208 hr = CoGetMalloc(MEMCTX_SAME, &imalloc);
3209 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3210 ok(imalloc == NULL, "got %p\n", imalloc);
3212 imalloc = NULL;
3213 hr = CoGetMalloc(MEMCTX_TASK, &imalloc);
3214 ok(hr == S_OK, "got 0x%08x\n", hr);
3215 ok(imalloc != NULL, "got %p\n", imalloc);
3217 /* DidAlloc() */
3218 ptr = IMalloc_Alloc(imalloc, 16);
3219 ok(!!ptr, "Failed to allocate block.\n");
3221 ret = IMalloc_DidAlloc(imalloc, ptr);
3222 ok(ret == 1, "Unexpected return value %d.\n", ret);
3224 ret = IMalloc_DidAlloc(imalloc, NULL);
3225 ok(ret == -1, "Unexpected return value %d.\n", ret);
3227 ret = IMalloc_DidAlloc(imalloc, (void *)0x1);
3228 ok(ret == 0, "Unexpected return value %d.\n", ret);
3230 ret = IMalloc_DidAlloc(imalloc, ptr + 4);
3231 ok(ret == 0, "Unexpected return value %d.\n", ret);
3233 /* GetSize() */
3234 size = IMalloc_GetSize(imalloc, NULL);
3235 ok(size == (SIZE_T)-1, "Unexpected return value.\n");
3237 size = IMalloc_GetSize(imalloc, ptr);
3238 ok(size == 16, "Unexpected return value.\n");
3240 IMalloc_Free(imalloc, ptr);
3242 IMalloc_Release(imalloc);
3245 static void test_CoGetApartmentType(void)
3247 APTTYPEQUALIFIER qualifier;
3248 APTTYPE type;
3249 HRESULT hr;
3251 if (!pCoGetApartmentType)
3253 win_skip("CoGetApartmentType not present\n");
3254 return;
3257 hr = pCoGetApartmentType(NULL, NULL);
3258 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3260 type = 0xdeadbeef;
3261 hr = pCoGetApartmentType(&type, NULL);
3262 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3263 ok(type == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", type);
3265 qualifier = 0xdeadbeef;
3266 hr = pCoGetApartmentType(NULL, &qualifier);
3267 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3268 ok(qualifier == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", qualifier);
3270 type = 0xdeadbeef;
3271 qualifier = 0xdeadbeef;
3272 hr = pCoGetApartmentType(&type, &qualifier);
3273 ok(hr == CO_E_NOTINITIALIZED, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3274 ok(type == APTTYPE_CURRENT, "Expected APTTYPE_CURRENT, got %u\n", type);
3275 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3277 type = 0xdeadbeef;
3278 qualifier = 0xdeadbeef;
3279 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3280 ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr);
3281 hr = pCoGetApartmentType(&type, &qualifier);
3282 ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr);
3283 ok(type == APTTYPE_MAINSTA, "Expected APTTYPE_MAINSTA, got %u\n", type);
3284 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3285 CoUninitialize();
3287 type = 0xdeadbeef;
3288 qualifier = 0xdeadbeef;
3289 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
3290 ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr);
3291 hr = pCoGetApartmentType(&type, &qualifier);
3292 ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr);
3293 ok(type == APTTYPE_MTA, "Expected APTTYPE_MTA, got %u\n", type);
3294 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3295 CoUninitialize();
3298 static HRESULT WINAPI testspy_QI(IMallocSpy *iface, REFIID riid, void **obj)
3300 if (IsEqualIID(riid, &IID_IMallocSpy) || IsEqualIID(riid, &IID_IUnknown))
3302 *obj = iface;
3303 IMallocSpy_AddRef(iface);
3304 return S_OK;
3307 return E_NOINTERFACE;
3310 static ULONG WINAPI testspy_AddRef(IMallocSpy *iface)
3312 return 2;
3315 static ULONG WINAPI testspy_Release(IMallocSpy *iface)
3317 return 1;
3320 static SIZE_T WINAPI testspy_PreAlloc(IMallocSpy *iface, SIZE_T cb)
3322 ok(0, "unexpected call\n");
3323 return 0;
3326 static void* WINAPI testspy_PostAlloc(IMallocSpy *iface, void *ptr)
3328 ok(0, "unexpected call\n");
3329 return NULL;
3332 static void* WINAPI testspy_PreFree(IMallocSpy *iface, void *ptr, BOOL spyed)
3334 ok(0, "unexpected call\n");
3335 return NULL;
3338 static void WINAPI testspy_PostFree(IMallocSpy *iface, BOOL spyed)
3340 ok(0, "unexpected call\n");
3343 static SIZE_T WINAPI testspy_PreRealloc(IMallocSpy *iface, void *ptr, SIZE_T cb, void **newptr, BOOL spyed)
3345 ok(0, "unexpected call\n");
3346 return 0;
3349 static void* WINAPI testspy_PostRealloc(IMallocSpy *iface, void *ptr, BOOL spyed)
3351 ok(0, "unexpected call\n");
3352 return NULL;
3355 static void* WINAPI testspy_PreGetSize(IMallocSpy *iface, void *ptr, BOOL spyed)
3357 ok(0, "unexpected call\n");
3358 return NULL;
3361 static SIZE_T WINAPI testspy_PostGetSize(IMallocSpy *iface, SIZE_T actual, BOOL spyed)
3363 ok(0, "unexpected call\n");
3364 return 0;
3367 static void* WINAPI testspy_PreDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed)
3369 ok(0, "unexpected call\n");
3370 return NULL;
3373 static int WINAPI testspy_PostDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed, int actual)
3375 ok(0, "unexpected call\n");
3376 return 0;
3379 static void WINAPI testspy_PreHeapMinimize(IMallocSpy *iface)
3381 ok(0, "unexpected call\n");
3384 static void WINAPI testspy_PostHeapMinimize(IMallocSpy *iface)
3386 ok(0, "unexpected call\n");
3389 static const IMallocSpyVtbl testspyvtbl =
3391 testspy_QI,
3392 testspy_AddRef,
3393 testspy_Release,
3394 testspy_PreAlloc,
3395 testspy_PostAlloc,
3396 testspy_PreFree,
3397 testspy_PostFree,
3398 testspy_PreRealloc,
3399 testspy_PostRealloc,
3400 testspy_PreGetSize,
3401 testspy_PostGetSize,
3402 testspy_PreDidAlloc,
3403 testspy_PostDidAlloc,
3404 testspy_PreHeapMinimize,
3405 testspy_PostHeapMinimize
3408 static IMallocSpy testspy = { &testspyvtbl };
3410 static void test_IMallocSpy(void)
3412 IMalloc *imalloc;
3413 HRESULT hr;
3415 hr = CoRegisterMallocSpy(NULL);
3416 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3418 hr = CoRevokeMallocSpy();
3419 ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr);
3421 hr = CoRegisterMallocSpy(&testspy);
3422 ok(hr == S_OK, "got 0x%08x\n", hr);
3424 hr = CoRegisterMallocSpy(NULL);
3425 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3427 hr = CoRegisterMallocSpy(&testspy);
3428 ok(hr == CO_E_OBJISREG, "got 0x%08x\n", hr);
3430 imalloc = NULL;
3431 hr = CoGetMalloc(MEMCTX_TASK, &imalloc);
3432 ok(hr == S_OK, "got 0x%08x\n", hr);
3433 ok(imalloc != NULL, "got %p\n", imalloc);
3435 IMalloc_Free(imalloc, NULL);
3437 IMalloc_Release(imalloc);
3439 hr = CoRevokeMallocSpy();
3440 ok(hr == S_OK, "got 0x%08x\n", hr);
3442 hr = CoRevokeMallocSpy();
3443 ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr);
3446 static void test_CoGetCurrentLogicalThreadId(void)
3448 HRESULT hr;
3449 GUID id;
3451 hr = CoGetCurrentLogicalThreadId(NULL);
3452 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3454 id = GUID_NULL;
3455 hr = CoGetCurrentLogicalThreadId(&id);
3456 ok(hr == S_OK, "got 0x%08x\n", hr);
3457 ok(!IsEqualGUID(&id, &GUID_NULL), "got null id\n");
3460 static HRESULT WINAPI testinitialize_QI(IInitializeSpy *iface, REFIID riid, void **obj)
3462 if (IsEqualIID(riid, &IID_IInitializeSpy) || IsEqualIID(riid, &IID_IUnknown))
3464 *obj = iface;
3465 IInitializeSpy_AddRef(iface);
3466 return S_OK;
3469 *obj = NULL;
3470 return E_NOINTERFACE;
3473 static ULONG WINAPI testinitialize_AddRef(IInitializeSpy *iface)
3475 return 2;
3478 static ULONG WINAPI testinitialize_Release(IInitializeSpy *iface)
3480 return 1;
3483 static DWORD expected_coinit_flags;
3484 static ULARGE_INTEGER init_cookies[3];
3485 static BOOL revoke_spies_on_uninit;
3487 static HRESULT WINAPI testinitialize_PreInitialize(IInitializeSpy *iface, DWORD coinit, DWORD aptrefs)
3489 CHECK_EXPECT2(PreInitialize);
3490 ok(coinit == expected_coinit_flags, "Unexpected init flags %#x, expected %#x.\n", coinit, expected_coinit_flags);
3491 return S_OK;
3494 static HRESULT WINAPI testinitialize_PostInitialize(IInitializeSpy *iface, HRESULT hr, DWORD coinit, DWORD aptrefs)
3496 CHECK_EXPECT2(PostInitialize);
3497 ok(coinit == expected_coinit_flags, "Unexpected init flags %#x, expected %#x.\n", coinit, expected_coinit_flags);
3498 return hr;
3501 static HRESULT WINAPI testinitialize_PreUninitialize(IInitializeSpy *iface, DWORD aptrefs)
3503 HRESULT hr;
3504 CHECK_EXPECT2(PreUninitialize);
3505 if (revoke_spies_on_uninit)
3507 hr = CoRevokeInitializeSpy(init_cookies[0]);
3508 ok(hr == S_OK, "got 0x%08x\n", hr);
3510 hr = CoRevokeInitializeSpy(init_cookies[1]);
3511 ok(hr == S_OK, "got 0x%08x\n", hr);
3513 hr = CoRevokeInitializeSpy(init_cookies[2]);
3514 ok(hr == S_OK, "got 0x%08x\n", hr);
3516 revoke_spies_on_uninit = FALSE;
3518 return S_OK;
3521 static HRESULT WINAPI testinitialize_PostUninitialize(IInitializeSpy *iface, DWORD aptrefs)
3523 CHECK_EXPECT2(PostUninitialize);
3524 return E_NOTIMPL;
3527 static const IInitializeSpyVtbl testinitializevtbl =
3529 testinitialize_QI,
3530 testinitialize_AddRef,
3531 testinitialize_Release,
3532 testinitialize_PreInitialize,
3533 testinitialize_PostInitialize,
3534 testinitialize_PreUninitialize,
3535 testinitialize_PostUninitialize
3538 static IInitializeSpy testinitialize = { &testinitializevtbl };
3540 static DWORD WINAPI test_init_spies_proc(void *arg)
3542 HRESULT hr;
3544 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
3545 ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr);
3547 hr = CoRevokeInitializeSpy(init_cookies[2]);
3548 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3550 CoUninitialize();
3551 return 0;
3554 static void test_IInitializeSpy(BOOL mt)
3556 HRESULT hr;
3558 if (mt)
3560 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
3561 ok(hr == S_OK, "CoInitializeEx failed: %#x\n", hr);
3564 hr = CoRegisterInitializeSpy(NULL, NULL);
3565 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3567 init_cookies[0].QuadPart = 1;
3568 hr = CoRegisterInitializeSpy(NULL, &init_cookies[0]);
3569 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3570 ok(init_cookies[0].QuadPart == 1, "got wrong cookie\n");
3572 hr = CoRegisterInitializeSpy(&testinitialize, NULL);
3573 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3575 init_cookies[0].HighPart = 0;
3576 init_cookies[0].LowPart = 1;
3577 hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[0]);
3578 ok(hr == S_OK, "got 0x%08x\n", hr);
3579 ok(init_cookies[0].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[0].HighPart,
3580 GetCurrentThreadId());
3581 if (!mt) ok(init_cookies[0].LowPart == 0, "got wrong low part 0x%x\n", init_cookies[0].LowPart);
3583 /* register same instance one more time */
3584 init_cookies[1].HighPart = 0;
3585 init_cookies[1].LowPart = 0;
3586 hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[1]);
3587 ok(hr == S_OK, "got 0x%08x\n", hr);
3588 ok(init_cookies[1].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[1].HighPart,
3589 GetCurrentThreadId());
3590 if (!mt) ok(init_cookies[1].LowPart == 1, "got wrong low part 0x%x\n", init_cookies[1].LowPart);
3592 init_cookies[2].HighPart = 0;
3593 init_cookies[2].LowPart = 0;
3594 hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[2]);
3595 ok(hr == S_OK, "got 0x%08x\n", hr);
3596 ok(init_cookies[2].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[2].HighPart,
3597 GetCurrentThreadId());
3598 if (!mt) ok(init_cookies[2].LowPart == 2, "got wrong low part 0x%x\n", init_cookies[2].LowPart);
3600 hr = CoRevokeInitializeSpy(init_cookies[1]);
3601 ok(hr == S_OK, "got 0x%08x\n", hr);
3603 hr = CoRevokeInitializeSpy(init_cookies[1]);
3604 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3606 init_cookies[1].HighPart = 0;
3607 init_cookies[1].LowPart = 0;
3608 hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[1]);
3609 ok(hr == S_OK, "got 0x%08x\n", hr);
3610 ok(init_cookies[1].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[1].HighPart,
3611 GetCurrentThreadId());
3612 if (!mt) ok(init_cookies[1].LowPart == 1, "got wrong low part 0x%x\n", init_cookies[1].LowPart);
3614 SET_EXPECT(PreInitialize);
3615 SET_EXPECT(PostInitialize);
3616 hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE));
3617 ok(hr == (mt ? S_FALSE : S_OK), "Failed to initialize COM, hr %#x.\n", hr);
3618 CHECK_CALLED(PreInitialize, 3);
3619 CHECK_CALLED(PostInitialize, 3);
3621 if (mt)
3623 HANDLE thread;
3624 thread = CreateThread(NULL, 0, test_init_spies_proc, NULL, 0, NULL);
3625 ok(thread != NULL, "CreateThread failed: %u\n", GetLastError());
3626 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
3629 SET_EXPECT(PreInitialize);
3630 SET_EXPECT(PostInitialize);
3631 hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE));
3632 ok(hr == S_FALSE, "Failed to initialize COM, hr %#x.\n", hr);
3633 CHECK_CALLED(PreInitialize, 3);
3634 CHECK_CALLED(PostInitialize, 3);
3636 SET_EXPECT(PreUninitialize);
3637 SET_EXPECT(PostUninitialize);
3638 CoUninitialize();
3639 CHECK_CALLED(PreUninitialize, 3);
3640 CHECK_CALLED(PostUninitialize, 3);
3642 SET_EXPECT(PreUninitialize);
3643 SET_EXPECT(PostUninitialize);
3644 CoUninitialize();
3645 CHECK_CALLED(PreUninitialize, 3);
3646 CHECK_CALLED(PostUninitialize, 3);
3648 if (mt)
3650 SET_EXPECT(PreUninitialize);
3651 SET_EXPECT(PostUninitialize);
3652 CoUninitialize();
3653 CHECK_CALLED(PreUninitialize, 3);
3654 CHECK_CALLED(PostUninitialize, 3);
3657 SET_EXPECT(PreInitialize);
3658 SET_EXPECT(PostInitialize);
3659 hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE));
3660 ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr);
3661 CHECK_CALLED(PreInitialize, 3);
3662 CHECK_CALLED(PostInitialize, 3);
3664 SET_EXPECT(PreUninitialize);
3665 revoke_spies_on_uninit = TRUE;
3666 CoUninitialize();
3667 CHECK_CALLED(PreUninitialize, 1);
3670 static HRESULT g_persistfile_qi_ret;
3671 static HRESULT g_persistfile_load_ret;
3672 static HRESULT WINAPI testinstance_QI(IPersistFile *iface, REFIID riid, void **obj)
3674 if (IsEqualIID(riid, &IID_IUnknown)) {
3675 *obj = iface;
3676 IUnknown_AddRef(iface);
3677 return S_OK;
3680 if (IsEqualIID(riid, &IID_IPersistFile)) {
3681 if (SUCCEEDED(g_persistfile_qi_ret)) {
3682 *obj = iface;
3683 IUnknown_AddRef(iface);
3685 else
3686 *obj = NULL;
3687 return g_persistfile_qi_ret;
3690 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
3691 *obj = NULL;
3692 return E_NOINTERFACE;
3695 static ULONG WINAPI testinstance_AddRef(IPersistFile *iface)
3697 return 2;
3700 static ULONG WINAPI testinstance_Release(IPersistFile *iface)
3702 return 1;
3705 static HRESULT WINAPI testinstance_GetClassID(IPersistFile *iface, CLSID *clsid)
3707 ok(0, "unexpected call\n");
3708 return E_NOTIMPL;
3711 static HRESULT WINAPI testinstance_IsDirty(IPersistFile *iface)
3713 ok(0, "unexpected call\n");
3714 return E_NOTIMPL;
3717 static HRESULT WINAPI testinstance_Load(IPersistFile *iface, LPCOLESTR filename, DWORD mode)
3719 return g_persistfile_load_ret;
3722 static HRESULT WINAPI testinstance_Save(IPersistFile *iface, LPCOLESTR filename, BOOL remember)
3724 return E_NOTIMPL;
3727 static HRESULT WINAPI testinstance_SaveCompleted(IPersistFile *iface, LPCOLESTR filename)
3729 ok(0, "unexpected call\n");
3730 return E_NOTIMPL;
3733 static HRESULT WINAPI testinstance_GetCurFile(IPersistFile *iface, LPOLESTR *filename)
3735 ok(0, "unexpected call\n");
3736 return E_NOTIMPL;
3739 static const IPersistFileVtbl testpersistfilevtbl = {
3740 testinstance_QI,
3741 testinstance_AddRef,
3742 testinstance_Release,
3743 testinstance_GetClassID,
3744 testinstance_IsDirty,
3745 testinstance_Load,
3746 testinstance_Save,
3747 testinstance_SaveCompleted,
3748 testinstance_GetCurFile
3751 static IPersistFile testpersistfile = { &testpersistfilevtbl };
3753 static HRESULT WINAPI getinstance_cf_QI(IClassFactory *iface, REFIID riid, void **obj)
3755 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) {
3756 *obj = iface;
3757 IClassFactory_AddRef(iface);
3758 return S_OK;
3761 *obj = NULL;
3762 return E_NOINTERFACE;
3765 static ULONG WINAPI getinstance_cf_AddRef(IClassFactory *iface)
3767 return 2;
3770 static ULONG WINAPI getinstance_cf_Release(IClassFactory *iface)
3772 return 1;
3775 static HRESULT WINAPI getinstance_cf_CreateInstance(IClassFactory *iface, IUnknown *outer,
3776 REFIID riid, void **obj)
3778 if (IsEqualIID(riid, &IID_IUnknown)) {
3779 *obj = &testpersistfile;
3780 return S_OK;
3783 ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid));
3784 *obj = NULL;
3785 return E_NOTIMPL;
3788 static HRESULT WINAPI getinstance_cf_LockServer(IClassFactory *iface, BOOL lock)
3790 ok(0, "unexpected call\n");
3791 return E_NOTIMPL;
3794 static const IClassFactoryVtbl getinstance_cf_vtbl = {
3795 getinstance_cf_QI,
3796 getinstance_cf_AddRef,
3797 getinstance_cf_Release,
3798 getinstance_cf_CreateInstance,
3799 getinstance_cf_LockServer
3802 static IClassFactory getinstance_cf = { &getinstance_cf_vtbl };
3804 static void test_CoGetInstanceFromFile(void)
3806 static const WCHAR filenameW[] = {'d','u','m','m','y','p','a','t','h',0};
3807 CLSID *clsid = (CLSID*)&CLSID_testclsid;
3808 MULTI_QI mqi[2];
3809 DWORD cookie;
3810 HRESULT hr;
3812 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3813 ok(hr == S_OK, "got 0x%08x\n", hr);
3815 /* CLSID is not specified, file does not exist */
3816 mqi[0].pIID = &IID_IUnknown;
3817 mqi[0].pItf = NULL;
3818 mqi[0].hr = E_NOTIMPL;
3819 hr = CoGetInstanceFromFile(NULL, NULL, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3820 todo_wine
3821 ok(hr == MK_E_CANTOPENFILE, "got 0x%08x\n", hr);
3822 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3823 ok(mqi[0].hr == E_NOINTERFACE, "got 0x%08x\n", mqi[0].hr);
3825 /* class is not available */
3826 mqi[0].pIID = &IID_IUnknown;
3827 mqi[0].pItf = NULL;
3828 mqi[0].hr = E_NOTIMPL;
3829 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3830 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
3831 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3832 ok(mqi[0].hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", mqi[0].hr);
3834 hr = CoRegisterClassObject(clsid, (IUnknown*)&getinstance_cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE,
3835 &cookie);
3836 ok(hr == S_OK, "got 0x%08x\n", hr);
3838 mqi[0].pIID = &IID_IUnknown;
3839 mqi[0].pItf = (void*)0xdeadbeef;
3840 mqi[0].hr = S_OK;
3841 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3842 todo_wine {
3843 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3844 ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf);
3846 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3848 mqi[0].pIID = &IID_IUnknown;
3849 mqi[0].pItf = (void*)0xdeadbeef;
3850 mqi[0].hr = E_NOTIMPL;
3851 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3852 todo_wine {
3853 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3854 ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf);
3855 ok(mqi[0].hr == E_NOTIMPL, "got 0x%08x\n", mqi[0].hr);
3857 mqi[0].pIID = &IID_IUnknown;
3858 mqi[0].pItf = NULL;
3859 mqi[0].hr = E_NOTIMPL;
3860 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3861 ok(hr == S_OK, "got 0x%08x\n", hr);
3862 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3863 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3865 mqi[0].pIID = &IID_IUnknown;
3866 mqi[0].pItf = NULL;
3867 mqi[0].hr = S_OK;
3868 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3869 ok(hr == S_OK, "got 0x%08x\n", hr);
3870 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3871 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3873 mqi[0].pIID = &IID_IUnknown;
3874 mqi[0].pItf = NULL;
3875 mqi[0].hr = S_OK;
3876 g_persistfile_qi_ret = S_FALSE;
3877 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3878 ok(hr == S_OK, "got 0x%08x\n", hr);
3879 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3880 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3881 g_persistfile_qi_ret = S_OK;
3883 mqi[0].pIID = &IID_IUnknown;
3884 mqi[0].pItf = NULL;
3885 mqi[0].hr = S_OK;
3886 mqi[1].pIID = &IID_IUnknown;
3887 mqi[1].pItf = NULL;
3888 mqi[1].hr = S_OK;
3889 g_persistfile_qi_ret = 0x8000efef;
3890 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi);
3891 ok(hr == 0x8000efef, "got 0x%08x\n", hr);
3892 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3893 ok(mqi[0].hr == 0x8000efef, "got 0x%08x\n", mqi[0].hr);
3894 ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf);
3895 ok(mqi[1].hr == 0x8000efef, "got 0x%08x\n", mqi[1].hr);
3896 g_persistfile_qi_ret = S_OK;
3898 mqi[0].pIID = &IID_IUnknown;
3899 mqi[0].pItf = NULL;
3900 mqi[0].hr = S_OK;
3901 mqi[1].pIID = &IID_IUnknown;
3902 mqi[1].pItf = NULL;
3903 mqi[1].hr = S_OK;
3904 g_persistfile_load_ret = 0x8000fefe;
3905 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi);
3906 ok(hr == 0x8000fefe, "got 0x%08x\n", hr);
3907 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3908 ok(mqi[0].hr == 0x8000fefe, "got 0x%08x\n", mqi[0].hr);
3909 ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf);
3910 ok(mqi[1].hr == 0x8000fefe, "got 0x%08x\n", mqi[1].hr);
3911 g_persistfile_load_ret = S_OK;
3913 hr = CoRevokeClassObject(cookie);
3914 ok(hr == S_OK, "got 0x%08x\n", hr);
3916 CoUninitialize();
3919 static void test_GlobalOptions(void)
3921 IGlobalOptions *global_options;
3922 ULONG_PTR value;
3923 HRESULT hres;
3925 CoInitialize(NULL);
3927 hres = CoCreateInstance(&CLSID_GlobalOptions, NULL, CLSCTX_INPROC_SERVER,
3928 &IID_IGlobalOptions, (void**)&global_options);
3929 ok(hres == S_OK || broken(hres == E_NOINTERFACE), "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres);
3930 if(FAILED(hres))
3932 win_skip("CLSID_GlobalOptions not available\n");
3933 CoUninitialize();
3934 return;
3937 hres = IGlobalOptions_Query(global_options, 0, &value);
3938 ok(FAILED(hres), "Unexpected hr %#x.\n", hres);
3940 hres = IGlobalOptions_Query(global_options, COMGLB_PROPERTIES_RESERVED3 + 1, &value);
3941 ok(FAILED(hres), "Unexpected hr %#x.\n", hres);
3943 value = ~0u;
3944 hres = IGlobalOptions_Query(global_options, COMGLB_EXCEPTION_HANDLING, &value);
3945 ok(hres == S_OK || broken(hres == E_FAIL) /* Vista */, "Unexpected hr %#x.\n", hres);
3946 if (SUCCEEDED(hres))
3947 ok(value == COMGLB_EXCEPTION_HANDLE, "Unexpected value %ld.\n", value);
3949 IGlobalOptions_Release(global_options);
3951 hres = CoCreateInstance(&CLSID_GlobalOptions, (IUnknown*)0xdeadbeef, CLSCTX_INPROC_SERVER,
3952 &IID_IGlobalOptions, (void**)&global_options);
3953 ok(hres == E_INVALIDARG, "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres);
3955 CoUninitialize();
3958 static void init_funcs(void)
3960 HMODULE hOle32 = GetModuleHandleA("ole32");
3961 HMODULE hAdvapi32 = GetModuleHandleA("advapi32");
3962 HMODULE hkernel32 = GetModuleHandleA("kernel32");
3964 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
3965 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
3966 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
3967 pCoGetApartmentType = (void*)GetProcAddress(hOle32, "CoGetApartmentType");
3968 pCoIncrementMTAUsage = (void*)GetProcAddress(hOle32, "CoIncrementMTAUsage");
3969 pCoDecrementMTAUsage = (void*)GetProcAddress(hOle32, "CoDecrementMTAUsage");
3970 pCoCreateInstanceFromApp = (void*)GetProcAddress(hOle32, "CoCreateInstanceFromApp");
3971 pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA");
3972 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
3974 pIsWow64Process = (void*)GetProcAddress(hkernel32, "IsWow64Process");
3977 static DWORD CALLBACK implicit_mta_proc(void *param)
3979 IComThreadingInfo *threading_info;
3980 ULONG_PTR token;
3981 IUnknown *unk;
3982 DWORD cookie;
3983 CLSID clsid;
3984 HRESULT hr;
3986 test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA);
3988 hr = CoCreateInstance(&CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
3989 ok_ole_success(hr, "CoCreateInstance");
3990 IUnknown_Release(unk);
3992 hr = CoGetClassObject(&CLSID_InternetZoneManager, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&unk);
3993 ok_ole_success(hr, "CoGetClassObject");
3994 IUnknown_Release(unk);
3996 hr = CoGetObjectContext(&IID_IComThreadingInfo, (void **)&threading_info);
3997 ok_ole_success(hr, "CoGetObjectContext");
3998 IComThreadingInfo_Release(threading_info);
4000 hr = CoGetContextToken(&token);
4001 ok_ole_success(hr, "CoGetContextToken");
4003 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
4004 ok_ole_success(hr, "CoRegisterPSClsid");
4006 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
4007 ok_ole_success(hr, "CoGetPSClsid");
4009 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
4010 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
4011 ok_ole_success(hr, "CoRegisterClassObject");
4013 hr = CoRevokeClassObject(cookie);
4014 ok_ole_success(hr, "CoRevokeClassObject");
4016 hr = CoRegisterMessageFilter(NULL, NULL);
4017 ok(hr == CO_E_NOT_SUPPORTED, "got %#x\n", hr);
4019 hr = CoLockObjectExternal(&Test_Unknown, TRUE, TRUE);
4020 ok_ole_success(hr, "CoLockObjectExternal");
4022 hr = CoDisconnectObject(&Test_Unknown, 0);
4023 ok_ole_success(hr, "CoDisconnectObject");
4025 return 0;
4028 /* Some COM functions (perhaps even all of them?) can make use of an "implicit"
4029 * multi-threaded apartment created by another thread in the same process. */
4030 static void test_implicit_mta(void)
4032 HANDLE thread;
4034 CoInitializeEx(NULL, COINIT_MULTITHREADED);
4036 thread = CreateThread(NULL, 0, implicit_mta_proc, NULL, 0, NULL);
4037 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
4039 CoUninitialize();
4042 static DWORD WINAPI co_get_current_process_thread(void *param)
4044 DWORD *id = param;
4046 *id = CoGetCurrentProcess();
4047 return 0;
4050 static void test_CoGetCurrentProcess(void)
4052 DWORD id, id2;
4053 HANDLE thread;
4055 id = CoGetCurrentProcess();
4056 ok(!!id && id != GetCurrentProcessId() && id != GetCurrentThreadId(), "Unexpected result %d.\n", id);
4058 id2 = 0;
4059 thread = CreateThread(NULL, 0, co_get_current_process_thread, &id2, 0, NULL);
4060 ok(thread != NULL, "Failed to create test thread.\n");
4061 ok(!WaitForSingleObject(thread, 10000), "Wait timed out.\n");
4062 CloseHandle(thread);
4064 ok(id2 && id2 != id, "Unexpected id from another thread.\n");
4067 static void test_mta_usage(void)
4069 CO_MTA_USAGE_COOKIE cookie, cookie2;
4070 HRESULT hr;
4072 if (!pCoIncrementMTAUsage)
4074 win_skip("CoIncrementMTAUsage() is not available.\n");
4075 return;
4078 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
4080 cookie = 0;
4081 hr = pCoIncrementMTAUsage(&cookie);
4082 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4083 ok(cookie != NULL, "Unexpected cookie %p.\n", cookie);
4085 cookie2 = 0;
4086 hr = pCoIncrementMTAUsage(&cookie2);
4087 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4088 ok(cookie2 != NULL && cookie2 != cookie, "Unexpected cookie %p.\n", cookie2);
4090 test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA);
4092 hr = pCoDecrementMTAUsage(cookie);
4093 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4095 test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA);
4097 hr = pCoDecrementMTAUsage(cookie2);
4098 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4100 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
4103 static void test_CoCreateInstanceFromApp(void)
4105 static const CLSID *supported_classes[] =
4107 &CLSID_InProcFreeMarshaler,
4108 &CLSID_GlobalOptions,
4109 &CLSID_StdGlobalInterfaceTable,
4111 static const CLSID *unsupported_classes[] =
4113 &CLSID_ManualResetEvent,
4115 unsigned int i;
4116 IUnknown *unk;
4117 DWORD cookie;
4118 MULTI_QI mqi;
4119 HRESULT hr;
4120 HANDLE handle;
4121 ULONG_PTR actctx_cookie;
4123 if (!pCoCreateInstanceFromApp)
4125 win_skip("CoCreateInstanceFromApp() is not available.\n");
4126 return;
4129 CoInitialize(NULL);
4131 for (i = 0; i < ARRAY_SIZE(supported_classes); ++i)
4133 memset(&mqi, 0, sizeof(mqi));
4134 mqi.pIID = &IID_IUnknown;
4135 hr = pCoCreateInstanceFromApp(supported_classes[i], NULL, CLSCTX_INPROC_SERVER, NULL, 1, &mqi);
4136 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4137 IUnknown_Release(mqi.pItf);
4139 hr = CoCreateInstance(supported_classes[i], NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
4140 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4141 IUnknown_Release(unk);
4144 for (i = 0; i < ARRAY_SIZE(unsupported_classes); ++i)
4146 memset(&mqi, 0, sizeof(mqi));
4147 mqi.pIID = &IID_IUnknown;
4148 hr = pCoCreateInstanceFromApp(unsupported_classes[i], NULL, CLSCTX_INPROC_SERVER, NULL, 1, &mqi);
4149 ok(hr == REGDB_E_CLASSNOTREG, "Unexpected hr %#x.\n", hr);
4151 hr = CoCreateInstance(unsupported_classes[i], NULL, CLSCTX_INPROC_SERVER | CLSCTX_APPCONTAINER,
4152 &IID_IUnknown, (void **)&unk);
4153 ok(hr == REGDB_E_CLASSNOTREG, "Unexpected hr %#x.\n", hr);
4155 hr = CoCreateInstance(unsupported_classes[i], NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
4156 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4157 IUnknown_Release(unk);
4160 /* Locally registered classes are filtered out. */
4161 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER,
4162 REGCLS_MULTIPLEUSE, &cookie);
4163 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4165 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void **)&unk);
4166 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4168 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_APPCONTAINER, NULL,
4169 &IID_IClassFactory, (void **)&unk);
4170 todo_wine
4171 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4173 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
4174 ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
4176 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_INPROC_SERVER | CLSCTX_APPCONTAINER,
4177 &IID_IUnknown, (void **)&unk);
4178 ok(hr == REGDB_E_CLASSNOTREG, "Unexpected hr %#x.\n", hr);
4180 memset(&mqi, 0, sizeof(mqi));
4181 mqi.pIID = &IID_IUnknown;
4182 hr = pCoCreateInstanceFromApp(&CLSID_WineOOPTest, NULL, CLSCTX_INPROC_SERVER, NULL, 1, &mqi);
4183 ok(hr == REGDB_E_CLASSNOTREG, "Unexpected hr %#x.\n", hr);
4185 hr = CoRevokeClassObject(cookie);
4186 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4188 /* Activation context */
4189 if ((handle = activate_context(actctx_manifest, &actctx_cookie)))
4191 hr = CoCreateInstance(&IID_Testiface7, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
4192 ok(hr == 0x80001235, "Unexpected hr %#x.\n", hr);
4194 hr = CoCreateInstance(&IID_Testiface7, NULL, CLSCTX_INPROC_SERVER | CLSCTX_APPCONTAINER,
4195 &IID_IUnknown, (void **)&unk);
4196 ok(hr == 0x80001235, "Unexpected hr %#x.\n", hr);
4198 deactivate_context(handle, actctx_cookie);
4201 CoUninitialize();
4204 static void test_call_cancellation(void)
4206 HRESULT hr;
4208 /* Cancellation is disabled initially. */
4209 hr = CoDisableCallCancellation(NULL);
4210 ok(hr == CO_E_CANCEL_DISABLED, "Unexpected hr %#x.\n", hr);
4212 hr = CoEnableCallCancellation(NULL);
4213 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4215 hr = CoDisableCallCancellation(NULL);
4216 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4218 hr = CoDisableCallCancellation(NULL);
4219 ok(hr == CO_E_CANCEL_DISABLED, "Unexpected hr %#x.\n", hr);
4221 hr = CoEnableCallCancellation(NULL);
4222 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4224 /* Counter is not affected by initialization. */
4225 hr = CoInitialize(NULL);
4226 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4228 hr = CoDisableCallCancellation(NULL);
4229 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4231 hr = CoDisableCallCancellation(NULL);
4232 ok(hr == CO_E_CANCEL_DISABLED, "Unexpected hr %#x.\n", hr);
4234 hr = CoEnableCallCancellation(NULL);
4235 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4237 CoUninitialize();
4239 hr = CoDisableCallCancellation(NULL);
4240 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4242 hr = CoDisableCallCancellation(NULL);
4243 ok(hr == CO_E_CANCEL_DISABLED, "Unexpected hr %#x.\n", hr);
4245 /* It's cumulative. */
4246 hr = CoEnableCallCancellation(NULL);
4247 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4249 hr = CoEnableCallCancellation(NULL);
4250 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4252 hr = CoDisableCallCancellation(NULL);
4253 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4255 hr = CoDisableCallCancellation(NULL);
4256 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4258 hr = CoDisableCallCancellation(NULL);
4259 ok(hr == CO_E_CANCEL_DISABLED, "Unexpected hr %#x.\n", hr);
4262 enum oletlsflags
4264 OLETLS_UUIDINITIALIZED = 0x2,
4265 OLETLS_DISABLE_OLE1DDE = 0x40,
4266 OLETLS_APARTMENTTHREADED = 0x80,
4267 OLETLS_MULTITHREADED = 0x100,
4270 struct oletlsdata
4272 void *threadbase;
4273 void *smallocator;
4274 DWORD id;
4275 DWORD flags;
4278 static DWORD get_oletlsflags(void)
4280 struct oletlsdata *data = NtCurrentTeb()->ReservedForOle;
4281 return data ? data->flags : 0;
4284 static DWORD CALLBACK oletlsdata_test_thread(void *arg)
4286 IUnknown *unk;
4287 DWORD flags;
4288 HRESULT hr;
4290 hr = CoCreateInstance(&CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
4291 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4292 IUnknown_Release(unk);
4294 /* Flag is not set for implicit MTA. */
4295 flags = get_oletlsflags();
4296 ok(!(flags & OLETLS_MULTITHREADED), "Unexpected flags %#x.\n", flags);
4298 return 0;
4301 static void test_oletlsdata(void)
4303 HANDLE thread;
4304 DWORD flags;
4305 HRESULT hr;
4306 GUID guid;
4308 /* STA */
4309 hr = CoInitialize(NULL);
4310 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4311 flags = get_oletlsflags();
4312 ok(flags & OLETLS_APARTMENTTHREADED && !(flags & OLETLS_DISABLE_OLE1DDE), "Unexpected flags %#x.\n", flags);
4313 CoUninitialize();
4314 flags = get_oletlsflags();
4315 ok(!(flags & (OLETLS_APARTMENTTHREADED | OLETLS_MULTITHREADED | OLETLS_DISABLE_OLE1DDE)), "Unexpected flags %#x.\n", flags);
4317 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
4318 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4319 flags = get_oletlsflags();
4320 ok(flags & OLETLS_APARTMENTTHREADED && flags & OLETLS_DISABLE_OLE1DDE, "Unexpected flags %#x.\n", flags);
4321 CoUninitialize();
4322 flags = get_oletlsflags();
4323 ok(!(flags & (OLETLS_APARTMENTTHREADED | OLETLS_MULTITHREADED | OLETLS_DISABLE_OLE1DDE)), "Unexpected flags %#x.\n", flags);
4325 /* MTA */
4326 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
4327 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4328 flags = get_oletlsflags();
4329 ok(flags & OLETLS_MULTITHREADED && flags & OLETLS_DISABLE_OLE1DDE, "Unexpected flags %#x.\n", flags);
4331 /* Implicit case. */
4332 thread = CreateThread(NULL, 0, oletlsdata_test_thread, NULL, 0, &flags);
4333 ok(thread != NULL, "Failed to create a test thread, error %d.\n", GetLastError());
4334 ok(!WaitForSingleObject(thread, 5000), "Wait timed out.\n");
4335 CloseHandle(thread);
4337 CoUninitialize();
4338 flags = get_oletlsflags();
4339 ok(!(flags & (OLETLS_APARTMENTTHREADED | OLETLS_MULTITHREADED | OLETLS_DISABLE_OLE1DDE)), "Unexpected flags %#x.\n", flags);
4341 /* Thread ID. */
4342 flags = get_oletlsflags();
4343 ok(!(flags & OLETLS_UUIDINITIALIZED), "Unexpected flags %#x.\n", flags);
4345 hr = CoGetCurrentLogicalThreadId(&guid);
4346 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4348 flags = get_oletlsflags();
4349 ok(flags & OLETLS_UUIDINITIALIZED && !(flags & (OLETLS_APARTMENTTHREADED | OLETLS_MULTITHREADED)),
4350 "Unexpected flags %#x.\n", flags);
4353 START_TEST(compobj)
4355 init_funcs();
4357 GetTempPathA(ARRAY_SIZE(testlib), testlib);
4358 SetCurrentDirectoryA(testlib);
4359 lstrcatA(testlib, "\\testlib.dll");
4360 extract_resource("testlib.dll", "TESTDLL", testlib);
4362 test_oletlsdata();
4363 test_ProgIDFromCLSID();
4364 test_CLSIDFromProgID();
4365 test_CLSIDFromString();
4366 test_IIDFromString();
4367 test_StringFromGUID2();
4368 test_CoCreateInstance();
4369 test_ole_menu();
4370 test_CoGetClassObject();
4371 test_CoCreateInstanceEx();
4372 test_CoRegisterMessageFilter();
4373 test_CoRegisterPSClsid();
4374 test_CoGetPSClsid();
4375 test_CoUnmarshalInterface();
4376 test_CoGetInterfaceAndReleaseStream();
4377 test_CoMarshalInterface();
4378 test_CoMarshalInterThreadInterfaceInStream();
4379 test_CoRegisterClassObject();
4380 test_registered_object_thread_affinity();
4381 test_CoFreeUnusedLibraries();
4382 test_CoGetObjectContext();
4383 test_CoGetCallContext();
4384 test_CoGetContextToken();
4385 test_TreatAsClass();
4386 test_CoInitializeEx();
4387 test_OleInitialize_InitCounting();
4388 test_OleRegGetMiscStatus();
4389 test_CoCreateGuid();
4390 test_CoWaitForMultipleHandles();
4391 test_CoGetMalloc();
4392 test_OleRegGetUserType();
4393 test_CoGetApartmentType();
4394 test_IMallocSpy();
4395 test_CoGetCurrentLogicalThreadId();
4396 test_IInitializeSpy(FALSE);
4397 test_IInitializeSpy(TRUE);
4398 test_CoGetInstanceFromFile();
4399 test_GlobalOptions();
4400 test_implicit_mta();
4401 test_CoGetCurrentProcess();
4402 test_mta_usage();
4403 test_CoCreateInstanceFromApp();
4404 test_call_cancellation();
4406 DeleteFileA( testlib );