ole32/tests: Use the available ARRAY_SIZE() macro.
[wine.git] / dlls / ole32 / tests / compobj.c
blob352cfbf4e9a7a12374aeb801f1d689be6f4bd22a
1 /*
2 * Component Object Tests
4 * Copyright 2005 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #define CONST_VTABLE
24 #include <stdarg.h>
25 #include <stdio.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #define USE_COM_CONTEXT_DEF
30 #include "initguid.h"
31 #include "objbase.h"
32 #include "shlguid.h"
33 #include "urlmon.h" /* for CLSID_FileProtocol */
34 #include "dde.h"
35 #include "cguid.h"
37 #include "ctxtcall.h"
39 #include "wine/test.h"
41 #define DEFINE_EXPECT(func) \
42 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
44 #define SET_EXPECT(func) \
45 expect_ ## func = TRUE
47 #define CHECK_EXPECT2(func) \
48 do { \
49 ok(expect_ ##func, "unexpected call " #func "\n"); \
50 called_ ## func = TRUE; \
51 }while(0)
53 #define CHECK_EXPECT(func) \
54 do { \
55 CHECK_EXPECT2(func); \
56 expect_ ## func = FALSE; \
57 }while(0)
59 #define CHECK_CALLED(func) \
60 do { \
61 ok(called_ ## func, "expected " #func "\n"); \
62 expect_ ## func = called_ ## func = FALSE; \
63 }while(0)
65 DEFINE_EXPECT(CreateStub);
67 /* functions that are not present on all versions of Windows */
68 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
69 static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
70 static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
71 static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
72 static HRESULT (WINAPI * pCoTreatAsClass)(REFCLSID clsidOld, REFCLSID pClsidNew);
73 static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
74 static HRESULT (WINAPI * pCoGetApartmentType)(APTTYPE *type, APTTYPEQUALIFIER *qualifier);
75 static LONG (WINAPI * pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
76 static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
78 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
79 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
80 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
81 static BOOL (WINAPI *pIsWow64Process)(HANDLE, LPBOOL);
82 static void (WINAPI *pReleaseActCtx)(HANDLE);
84 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
85 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
86 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
88 static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
89 static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
90 static const GUID IID_Testiface = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
91 static const GUID IID_Testiface2 = { 0x32222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
92 static const GUID IID_Testiface3 = { 0x42222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
93 static const GUID IID_Testiface4 = { 0x52222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
94 static const GUID IID_Testiface5 = { 0x62222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
95 static const GUID IID_Testiface6 = { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
96 static const GUID IID_TestPS = { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } };
98 DEFINE_GUID(CLSID_InProcFreeMarshaler, 0x0000033a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
99 DEFINE_GUID(CLSID_testclsid, 0xacd014c7,0x9535,0x4fac,0x8b,0x53,0xa4,0x8c,0xa7,0xf4,0xd7,0x26);
100 DEFINE_GUID(CLSID_GlobalOptions, 0x0000034b,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
102 static const WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
103 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
104 static const WCHAR wszCLSID_StdFont[] =
106 '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
107 '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
109 static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
110 static const WCHAR cf_brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
111 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0};
113 DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
114 DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
116 static LONG cLocks;
118 static void LockModule(void)
120 InterlockedIncrement(&cLocks);
123 static void UnlockModule(void)
125 InterlockedDecrement(&cLocks);
128 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
129 LPCLASSFACTORY iface,
130 REFIID riid,
131 LPVOID *ppvObj)
133 if (ppvObj == NULL) return E_POINTER;
135 if (IsEqualGUID(riid, &IID_IUnknown) ||
136 IsEqualGUID(riid, &IID_IClassFactory))
138 *ppvObj = iface;
139 IClassFactory_AddRef(iface);
140 return S_OK;
143 *ppvObj = NULL;
144 return E_NOINTERFACE;
147 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
149 LockModule();
150 return 2; /* non-heap-based object */
153 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
155 UnlockModule();
156 return 1; /* non-heap-based object */
159 static IID create_instance_iid;
160 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
161 LPCLASSFACTORY iface,
162 IUnknown *pUnkOuter,
163 REFIID riid,
164 LPVOID *ppvObj)
166 *ppvObj = NULL;
167 create_instance_iid = *riid;
168 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
169 return E_NOINTERFACE;
172 static HRESULT WINAPI Test_IClassFactory_LockServer(
173 LPCLASSFACTORY iface,
174 BOOL fLock)
176 return S_OK;
179 static const IClassFactoryVtbl TestClassFactory_Vtbl =
181 Test_IClassFactory_QueryInterface,
182 Test_IClassFactory_AddRef,
183 Test_IClassFactory_Release,
184 Test_IClassFactory_CreateInstance,
185 Test_IClassFactory_LockServer
188 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
190 static WCHAR manifest_path[MAX_PATH];
192 static BOOL create_manifest_file(const char *filename, const char *manifest)
194 int manifest_len;
195 DWORD size;
196 HANDLE file;
197 WCHAR path[MAX_PATH];
199 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
200 GetFullPathNameW(path, ARRAY_SIZE(manifest_path), manifest_path, NULL);
202 manifest_len = strlen(manifest);
203 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
204 FILE_ATTRIBUTE_NORMAL, NULL);
205 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
206 if(file == INVALID_HANDLE_VALUE)
207 return FALSE;
208 WriteFile(file, manifest, manifest_len, &size, NULL);
209 CloseHandle(file);
211 return TRUE;
214 static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie)
216 WCHAR path[MAX_PATH];
217 ACTCTXW actctx;
218 HANDLE handle;
219 BOOL ret;
221 if (!pCreateActCtxW) return NULL;
223 create_manifest_file("file.manifest", manifest);
225 MultiByteToWideChar( CP_ACP, 0, "file.manifest", -1, path, MAX_PATH );
226 memset(&actctx, 0, sizeof(ACTCTXW));
227 actctx.cbSize = sizeof(ACTCTXW);
228 actctx.lpSource = path;
230 handle = pCreateActCtxW(&actctx);
231 ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* some old XP/2k3 versions */,
232 "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
233 if (handle == INVALID_HANDLE_VALUE)
235 win_skip("activation context generation failed, some tests will be skipped\n");
236 handle = NULL;
239 ok(actctx.cbSize == sizeof(ACTCTXW), "actctx.cbSize=%d\n", actctx.cbSize);
240 ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
241 ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
242 ok(actctx.wProcessorArchitecture == 0, "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
243 ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId);
244 ok(actctx.lpAssemblyDirectory == NULL, "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
245 ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
246 ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n", actctx.lpApplicationName);
247 ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
249 DeleteFileA("file.manifest");
251 if (handle)
253 ret = pActivateActCtx(handle, cookie);
254 ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
257 return handle;
260 static const char actctx_manifest[] =
261 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
262 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
263 " publicKeyToken=\"6595b6414666f1df\" />"
264 "<file name=\"testlib.dll\">"
265 " <comClass"
266 " clsid=\"{0000033a-0000-0000-c000-000000000046}\""
267 " progid=\"FTMarshal\""
268 " />"
269 " <comClass"
270 " clsid=\"{5201163f-8164-4fd0-a1a2-5d5a3654d3bd}\""
271 " progid=\"WineOOPTest\""
272 " />"
273 " <comClass description=\"Test com class\""
274 " clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
275 " progid=\"ProgId.ProgId\""
276 " miscStatusIcon=\"recomposeonresize\""
277 " />"
278 " <comClass description=\"CustomFont Description\" clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb851}\""
279 " progid=\"CustomFont\""
280 " miscStatusIcon=\"recomposeonresize\""
281 " miscStatusContent=\"insideout\""
282 " />"
283 " <comClass description=\"StdFont Description\" clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
284 " progid=\"StdFont\""
285 " />"
286 " <comClass clsid=\"{62222222-1234-1234-1234-56789abcdef0}\" >"
287 " <progid>ProgId.ProgId.1</progid>"
288 " </comClass>"
289 " <comInterfaceProxyStub "
290 " name=\"Iifaceps\""
291 " iid=\"{22222222-1234-1234-1234-56789abcdef0}\""
292 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
293 " />"
294 "</file>"
295 " <comInterfaceExternalProxyStub "
296 " name=\"Iifaceps2\""
297 " iid=\"{32222222-1234-1234-1234-56789abcdef0}\""
298 " />"
299 " <comInterfaceExternalProxyStub "
300 " name=\"Iifaceps3\""
301 " iid=\"{42222222-1234-1234-1234-56789abcdef0}\""
302 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
303 " />"
304 " <comInterfaceExternalProxyStub "
305 " name=\"Iifaceps4\""
306 " iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
307 " proxyStubClsid32=\"{00000000-0000-0000-0000-000000000000}\""
308 " />"
309 " <clrClass "
310 " clsid=\"{72222222-1234-1234-1234-56789abcdef0}\""
311 " name=\"clrclass\""
312 " >"
313 " <progid>clrprogid.1</progid>"
314 " </clrClass>"
315 "</assembly>";
317 DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
319 static void test_ProgIDFromCLSID(void)
321 ULONG_PTR cookie = 0;
322 LPWSTR progid;
323 HANDLE handle;
324 HRESULT hr;
326 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
327 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
328 if (hr == S_OK)
330 ok(!lstrcmpiW(progid, stdfont), "Didn't get expected prog ID\n");
331 CoTaskMemFree(progid);
334 progid = (LPWSTR)0xdeadbeef;
335 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
336 ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
337 ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
339 hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
340 ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
342 if ((handle = activate_context(actctx_manifest, &cookie)))
344 static const WCHAR customfontW[] = {'C','u','s','t','o','m','F','o','n','t',0};
346 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
347 ok(hr == S_OK, "got 0x%08x\n", hr);
348 ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid));
349 CoTaskMemFree(progid);
351 /* try something registered and redirected */
352 progid = NULL;
353 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
354 ok(hr == S_OK, "got 0x%08x\n", hr);
355 ok(!lstrcmpiW(progid, customfontW), "got wrong progid %s\n", wine_dbgstr_w(progid));
356 CoTaskMemFree(progid);
358 /* classes without default progid, progid list is not used */
359 progid = (void *)0xdeadbeef;
360 hr = ProgIDFromCLSID(&IID_Testiface5, &progid);
361 ok(hr == REGDB_E_CLASSNOTREG && progid == NULL, "got 0x%08x, progid %p\n", hr, progid);
363 progid = (void *)0xdeadbeef;
364 hr = ProgIDFromCLSID(&IID_Testiface6, &progid);
365 ok(hr == REGDB_E_CLASSNOTREG && progid == NULL, "got 0x%08x, progid %p\n", hr, progid);
367 pDeactivateActCtx(0, cookie);
368 pReleaseActCtx(handle);
372 static void test_CLSIDFromProgID(void)
374 ULONG_PTR cookie = 0;
375 HANDLE handle;
376 CLSID clsid;
377 HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
378 ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
379 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
381 hr = CLSIDFromString(stdfont, &clsid);
382 ok_ole_success(hr, "CLSIDFromString");
383 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
385 /* test some failure cases */
387 hr = CLSIDFromProgID(wszNonExistent, NULL);
388 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
390 hr = CLSIDFromProgID(NULL, &clsid);
391 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
393 memset(&clsid, 0xcc, sizeof(clsid));
394 hr = CLSIDFromProgID(wszNonExistent, &clsid);
395 ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
396 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
398 /* fails without proper context */
399 memset(&clsid, 0xcc, sizeof(clsid));
400 hr = CLSIDFromProgID(progidW, &clsid);
401 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
402 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "wrong clsid\n");
404 if ((handle = activate_context(actctx_manifest, &cookie)))
406 GUID clsid1;
408 memset(&clsid, 0xcc, sizeof(clsid));
409 hr = CLSIDFromProgID(wszNonExistent, &clsid);
410 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
411 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "should have zero CLSID on failure\n");
413 /* CLSIDFromString() doesn't check activation context */
414 hr = CLSIDFromString(progidW, &clsid);
415 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
417 clsid = CLSID_NULL;
418 hr = CLSIDFromProgID(progidW, &clsid);
419 ok(hr == S_OK, "got 0x%08x\n", hr);
420 /* it returns generated CLSID here */
421 ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL),
422 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid));
424 /* duplicate progid present in context - returns generated guid here too */
425 clsid = CLSID_NULL;
426 hr = CLSIDFromProgID(stdfont, &clsid);
427 ok(hr == S_OK, "got 0x%08x\n", hr);
428 clsid1 = CLSID_StdFont;
429 /* that's where it differs from StdFont */
430 clsid1.Data4[7] = 0x52;
431 ok(!IsEqualCLSID(&clsid, &CLSID_StdFont) && !IsEqualCLSID(&clsid, &CLSID_NULL) && !IsEqualCLSID(&clsid, &clsid1),
432 "got %s\n", wine_dbgstr_guid(&clsid));
434 pDeactivateActCtx(0, cookie);
435 pReleaseActCtx(handle);
439 static void test_CLSIDFromString(void)
441 CLSID clsid;
442 WCHAR wszCLSID_Broken[50];
443 UINT i;
445 HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
446 ok_ole_success(hr, "CLSIDFromString");
447 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
449 memset(&clsid, 0xab, sizeof(clsid));
450 hr = CLSIDFromString(NULL, &clsid);
451 ok(hr == S_OK, "got 0x%08x\n", hr);
452 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
454 /* string is longer, but starts with a valid CLSID */
455 memset(&clsid, 0, sizeof(clsid));
456 hr = CLSIDFromString(cf_brokenW, &clsid);
457 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
458 ok(IsEqualCLSID(&clsid, &IID_IClassFactory), "got %s\n", wine_dbgstr_guid(&clsid));
460 lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
461 for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
462 wszCLSID_Broken[i] = 'A';
463 wszCLSID_Broken[i] = '\0';
465 memset(&clsid, 0, sizeof(CLSID));
466 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
467 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
468 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
470 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
471 memset(&clsid, 0, sizeof(CLSID));
472 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
473 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
474 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
476 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
477 memset(&clsid, 0, sizeof(CLSID));
478 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
479 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
480 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
482 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
483 memset(&clsid, 0, sizeof(CLSID));
484 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
485 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
486 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
488 memset(&clsid, 0xcc, sizeof(CLSID));
489 hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
490 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
491 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
493 wszCLSID_Broken[9] = '*';
494 memset(&clsid, 0xcc, sizeof(CLSID));
495 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
496 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
497 ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
498 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
500 wszCLSID_Broken[3] = '*';
501 memset(&clsid, 0xcc, sizeof(CLSID));
502 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
503 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
504 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
505 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
507 wszCLSID_Broken[3] = '\0';
508 memset(&clsid, 0xcc, sizeof(CLSID));
509 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
510 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
511 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
512 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
515 static void test_IIDFromString(void)
517 static const WCHAR cfW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
518 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
519 static const WCHAR brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
520 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
521 static const WCHAR broken2W[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
522 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
523 static const WCHAR broken3W[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
524 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
525 HRESULT hr;
526 IID iid;
528 hr = IIDFromString(wszCLSID_StdFont, &iid);
529 ok(hr == S_OK, "got 0x%08x\n", hr);
530 ok(IsEqualIID(&iid, &CLSID_StdFont), "got iid %s\n", wine_dbgstr_guid(&iid));
532 memset(&iid, 0xab, sizeof(iid));
533 hr = IIDFromString(NULL, &iid);
534 ok(hr == S_OK, "got 0x%08x\n", hr);
535 ok(IsEqualIID(&iid, &CLSID_NULL), "got iid %s\n", wine_dbgstr_guid(&iid));
537 hr = IIDFromString(cfW, &iid);
538 ok(hr == S_OK, "got 0x%08x\n", hr);
539 ok(IsEqualIID(&iid, &IID_IClassFactory), "got iid %s\n", wine_dbgstr_guid(&iid));
541 /* string starts with a valid IID but is longer */
542 memset(&iid, 0xab, sizeof(iid));
543 hr = IIDFromString(cf_brokenW, &iid);
544 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
545 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
547 /* invalid IID in a valid format */
548 memset(&iid, 0xab, sizeof(iid));
549 hr = IIDFromString(brokenW, &iid);
550 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
551 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
553 memset(&iid, 0xab, sizeof(iid));
554 hr = IIDFromString(broken2W, &iid);
555 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
556 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
558 /* format is broken, but string length is okay */
559 memset(&iid, 0xab, sizeof(iid));
560 hr = IIDFromString(broken3W, &iid);
561 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
562 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
564 /* invalid string */
565 memset(&iid, 0xab, sizeof(iid));
566 hr = IIDFromString(wszNonExistent, &iid);
567 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
568 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
570 /* valid ProgID */
571 memset(&iid, 0xab, sizeof(iid));
572 hr = IIDFromString(stdfont, &iid);
573 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
574 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
577 static void test_StringFromGUID2(void)
579 WCHAR str[50];
580 int len;
582 /* invalid pointer */
583 SetLastError(0xdeadbeef);
584 len = StringFromGUID2(NULL,str,50);
585 ok(len == 0, "len: %d (expected 0)\n", len);
586 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
588 /* Test corner cases for buffer size */
589 len = StringFromGUID2(&CLSID_StdFont,str,50);
590 ok(len == 39, "len: %d (expected 39)\n", len);
591 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
593 memset(str,0,sizeof str);
594 len = StringFromGUID2(&CLSID_StdFont,str,39);
595 ok(len == 39, "len: %d (expected 39)\n", len);
596 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
598 len = StringFromGUID2(&CLSID_StdFont,str,38);
599 ok(len == 0, "len: %d (expected 0)\n", len);
601 len = StringFromGUID2(&CLSID_StdFont,str,30);
602 ok(len == 0, "len: %d (expected 0)\n", len);
605 #define test_apt_type(t, q) _test_apt_type(t, q, __LINE__)
606 static void _test_apt_type(APTTYPE expected_type, APTTYPEQUALIFIER expected_qualifier, int line)
608 APTTYPEQUALIFIER qualifier = ~0u;
609 APTTYPE type = ~0u;
610 HRESULT hr;
612 if (!pCoGetApartmentType)
613 return;
615 hr = pCoGetApartmentType(&type, &qualifier);
616 ok_(__FILE__, line)(hr == S_OK || hr == CO_E_NOTINITIALIZED, "Unexpected return code: 0x%08x\n", hr);
617 ok_(__FILE__, line)(type == expected_type, "Wrong apartment type %d, expected %d\n", type, expected_type);
618 ok_(__FILE__, line)(qualifier == expected_qualifier, "Wrong apartment qualifier %d, expected %d\n", qualifier,
619 expected_qualifier);
622 static void test_CoCreateInstance(void)
624 HRESULT hr;
625 IUnknown *pUnk;
626 REFCLSID rclsid = &CLSID_InternetZoneManager;
628 pUnk = (IUnknown *)0xdeadbeef;
629 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
630 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
631 ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
633 OleInitialize(NULL);
635 /* test errors returned for non-registered clsids */
636 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
637 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
638 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pUnk);
639 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
640 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (void **)&pUnk);
641 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
642 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_REMOTE_SERVER, &IID_IUnknown, (void **)&pUnk);
643 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
645 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
646 if(hr == REGDB_E_CLASSNOTREG)
648 skip("IE not installed so can't test CoCreateInstance\n");
649 OleUninitialize();
650 return;
653 ok_ole_success(hr, "CoCreateInstance");
654 if(pUnk) IUnknown_Release(pUnk);
655 OleUninitialize();
657 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
658 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
660 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
663 static void test_CoGetClassObject(void)
665 HRESULT hr;
666 HANDLE handle;
667 ULONG_PTR cookie;
668 IUnknown *pUnk;
669 REFCLSID rclsid = &CLSID_InternetZoneManager;
670 HKEY hkey;
671 LONG res;
673 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
674 ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
675 ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
677 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
678 ok(hr == E_INVALIDARG ||
679 broken(hr == CO_E_NOTINITIALIZED), /* win9x */
680 "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
682 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
684 if (!pRegOverridePredefKey)
686 win_skip("RegOverridePredefKey not available\n");
687 return;
690 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
692 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
693 if (hr == S_OK)
695 IUnknown_Release(pUnk);
697 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
698 KEY_ALL_ACCESS, NULL, &hkey, NULL);
699 ok(!res, "RegCreateKeyEx returned %d\n", res);
701 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
702 ok(!res, "RegOverridePredefKey returned %d\n", res);
704 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
705 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
707 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
708 ok(!res, "RegOverridePredefKey returned %d\n", res);
710 if (hr == S_OK) IUnknown_Release(pUnk);
711 RegCloseKey(hkey);
714 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
715 ok(hr == S_OK, "got 0x%08x\n", hr);
716 IUnknown_Release(pUnk);
718 /* context redefines FreeMarshaler CLSID */
719 if ((handle = activate_context(actctx_manifest, &cookie)))
721 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
722 ok(hr == S_OK, "got 0x%08x\n", hr);
723 IUnknown_Release(pUnk);
725 pDeactivateActCtx(0, cookie);
726 pReleaseActCtx(handle);
729 CoUninitialize();
732 static void test_CoCreateInstanceEx(void)
734 MULTI_QI qi_res = { &IID_IMoniker };
735 DWORD cookie;
736 HRESULT hr;
738 CoInitialize(NULL);
740 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
741 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
742 ok_ole_success(hr, "CoRegisterClassObject");
744 create_instance_iid = IID_NULL;
745 hr = CoCreateInstanceEx(&CLSID_WineOOPTest, NULL, CLSCTX_INPROC_SERVER, NULL, 1, &qi_res);
746 ok(hr == E_NOINTERFACE, "CoCreateInstanceEx failed: %08x\n", hr);
747 ok(IsEqualGUID(&create_instance_iid, qi_res.pIID), "Unexpected CreateInstance iid %s\n",
748 wine_dbgstr_guid(&create_instance_iid));
750 hr = CoRevokeClassObject(cookie);
751 ok_ole_success(hr, "CoRevokeClassObject");
753 CoUninitialize();
756 static ATOM register_dummy_class(void)
758 WNDCLASSA wc =
761 DefWindowProcA,
764 GetModuleHandleA(NULL),
765 NULL,
766 LoadCursorA(NULL, (LPSTR)IDC_ARROW),
767 (HBRUSH)(COLOR_BTNFACE+1),
768 NULL,
769 "WineOleTestClass",
772 return RegisterClassA(&wc);
775 static void test_ole_menu(void)
777 HWND hwndFrame;
778 HRESULT hr;
780 hwndFrame = CreateWindowA((LPCSTR)MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
781 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
782 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
784 DestroyWindow(hwndFrame);
788 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
790 if (ppvObj == NULL) return E_POINTER;
792 if (IsEqualGUID(riid, &IID_IUnknown) ||
793 IsEqualGUID(riid, &IID_IClassFactory))
795 *ppvObj = iface;
796 IMessageFilter_AddRef(iface);
797 return S_OK;
800 return E_NOINTERFACE;
803 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
805 return 2; /* non-heap object */
808 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
810 return 1; /* non-heap object */
813 static DWORD WINAPI MessageFilter_HandleInComingCall(
814 IMessageFilter *iface,
815 DWORD dwCallType,
816 HTASK threadIDCaller,
817 DWORD dwTickCount,
818 LPINTERFACEINFO lpInterfaceInfo)
820 trace("HandleInComingCall\n");
821 return SERVERCALL_ISHANDLED;
824 static DWORD WINAPI MessageFilter_RetryRejectedCall(
825 IMessageFilter *iface,
826 HTASK threadIDCallee,
827 DWORD dwTickCount,
828 DWORD dwRejectType)
830 trace("RetryRejectedCall\n");
831 return 0;
834 static DWORD WINAPI MessageFilter_MessagePending(
835 IMessageFilter *iface,
836 HTASK threadIDCallee,
837 DWORD dwTickCount,
838 DWORD dwPendingType)
840 trace("MessagePending\n");
841 todo_wine ok(0, "unexpected call\n");
842 return PENDINGMSG_WAITNOPROCESS;
845 static const IMessageFilterVtbl MessageFilter_Vtbl =
847 MessageFilter_QueryInterface,
848 MessageFilter_AddRef,
849 MessageFilter_Release,
850 MessageFilter_HandleInComingCall,
851 MessageFilter_RetryRejectedCall,
852 MessageFilter_MessagePending
855 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
857 static void test_CoRegisterMessageFilter(void)
859 HRESULT hr;
860 IMessageFilter *prev_filter;
862 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
863 ok(hr == CO_E_NOT_SUPPORTED,
864 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
865 hr);
867 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
868 prev_filter = (IMessageFilter *)0xdeadbeef;
869 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
870 ok(hr == CO_E_NOT_SUPPORTED,
871 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
872 hr);
873 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
874 "prev_filter should have been set to %p\n", prev_filter);
875 CoUninitialize();
877 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
879 hr = CoRegisterMessageFilter(NULL, NULL);
880 ok_ole_success(hr, "CoRegisterMessageFilter");
882 prev_filter = (IMessageFilter *)0xdeadbeef;
883 hr = CoRegisterMessageFilter(NULL, &prev_filter);
884 ok_ole_success(hr, "CoRegisterMessageFilter");
885 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
887 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
888 ok_ole_success(hr, "CoRegisterMessageFilter");
889 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
891 hr = CoRegisterMessageFilter(NULL, NULL);
892 ok_ole_success(hr, "CoRegisterMessageFilter");
894 CoUninitialize();
897 static IUnknown Test_Unknown;
899 static HRESULT WINAPI EnumOLEVERB_QueryInterface(IEnumOLEVERB *iface, REFIID riid, void **ppv)
901 return IUnknown_QueryInterface(&Test_Unknown, riid, ppv);
904 static ULONG WINAPI EnumOLEVERB_AddRef(IEnumOLEVERB *iface)
906 return 2;
909 static ULONG WINAPI EnumOLEVERB_Release(IEnumOLEVERB *iface)
911 return 1;
914 static HRESULT WINAPI EnumOLEVERB_Next(IEnumOLEVERB *iface, ULONG celt, OLEVERB *rgelt, ULONG *fetched)
916 ok(0, "unexpected call\n");
917 return E_NOTIMPL;
920 static HRESULT WINAPI EnumOLEVERB_Skip(IEnumOLEVERB *iface, ULONG celt)
922 ok(0, "unexpected call\n");
923 return E_NOTIMPL;
926 static HRESULT WINAPI EnumOLEVERB_Reset(IEnumOLEVERB *iface)
928 ok(0, "unexpected call\n");
929 return E_NOTIMPL;
932 static HRESULT WINAPI EnumOLEVERB_Clone(IEnumOLEVERB *iface, IEnumOLEVERB **ppenum)
934 ok(0, "unexpected call\n");
935 return E_NOTIMPL;
938 static const IEnumOLEVERBVtbl EnumOLEVERBVtbl = {
939 EnumOLEVERB_QueryInterface,
940 EnumOLEVERB_AddRef,
941 EnumOLEVERB_Release,
942 EnumOLEVERB_Next,
943 EnumOLEVERB_Skip,
944 EnumOLEVERB_Reset,
945 EnumOLEVERB_Clone
948 static IEnumOLEVERB EnumOLEVERB = { &EnumOLEVERBVtbl };
950 static HRESULT WINAPI Test_IUnknown_QueryInterface(
951 IUnknown *iface,
952 REFIID riid,
953 LPVOID *ppvObj)
955 if (ppvObj == NULL) return E_POINTER;
957 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IWineTest)) {
958 *ppvObj = iface;
959 }else if(IsEqualIID(riid, &IID_IEnumOLEVERB)) {
960 *ppvObj = &EnumOLEVERB;
961 }else {
962 *ppvObj = NULL;
963 return E_NOINTERFACE;
966 IUnknown_AddRef((IUnknown*)*ppvObj);
967 return S_OK;
970 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
972 return 2; /* non-heap-based object */
975 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
977 return 1; /* non-heap-based object */
980 static const IUnknownVtbl TestUnknown_Vtbl =
982 Test_IUnknown_QueryInterface,
983 Test_IUnknown_AddRef,
984 Test_IUnknown_Release,
987 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
989 static IPSFactoryBuffer *ps_factory_buffer;
991 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
992 IPSFactoryBuffer * This,
993 /* [in] */ REFIID riid,
994 /* [iid_is][out] */ void **ppvObject)
996 if (IsEqualIID(riid, &IID_IUnknown) ||
997 IsEqualIID(riid, &IID_IPSFactoryBuffer))
999 *ppvObject = This;
1000 IPSFactoryBuffer_AddRef(This);
1001 return S_OK;
1003 return E_NOINTERFACE;
1006 static ULONG WINAPI PSFactoryBuffer_AddRef(
1007 IPSFactoryBuffer * This)
1009 return 2;
1012 static ULONG WINAPI PSFactoryBuffer_Release(
1013 IPSFactoryBuffer * This)
1015 return 1;
1018 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
1019 IPSFactoryBuffer * This,
1020 /* [in] */ IUnknown *pUnkOuter,
1021 /* [in] */ REFIID riid,
1022 /* [out] */ IRpcProxyBuffer **ppProxy,
1023 /* [out] */ void **ppv)
1025 return E_NOTIMPL;
1028 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
1029 IPSFactoryBuffer * This,
1030 /* [in] */ REFIID riid,
1031 /* [unique][in] */ IUnknown *pUnkServer,
1032 /* [out] */ IRpcStubBuffer **ppStub)
1034 CHECK_EXPECT(CreateStub);
1036 ok(pUnkServer == (IUnknown*)&Test_Unknown, "unexpected pUnkServer %p\n", pUnkServer);
1037 if(!ps_factory_buffer)
1038 return E_NOTIMPL;
1040 return IPSFactoryBuffer_CreateStub(ps_factory_buffer, &IID_IEnumOLEVERB, pUnkServer, ppStub);
1043 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
1045 PSFactoryBuffer_QueryInterface,
1046 PSFactoryBuffer_AddRef,
1047 PSFactoryBuffer_Release,
1048 PSFactoryBuffer_CreateProxy,
1049 PSFactoryBuffer_CreateStub
1052 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
1054 static const CLSID CLSID_WineTestPSFactoryBuffer =
1056 0x52011640,
1057 0x8164,
1058 0x4fd0,
1059 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1060 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
1062 static DWORD CALLBACK register_ps_clsid_thread(void *context)
1064 HRESULT hr;
1065 CLSID clsid = {0};
1067 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1069 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1070 ok_ole_success(hr, "CoGetPSClsid");
1071 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1072 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1074 /* test registering a PSClsid in an apartment which is then destroyed */
1075 hr = CoRegisterPSClsid(&IID_TestPS, &clsid);
1076 ok_ole_success(hr, "CoRegisterPSClsid");
1078 CoUninitialize();
1080 return hr;
1083 static void test_CoRegisterPSClsid(void)
1085 HRESULT hr;
1086 DWORD dwRegistrationKey;
1087 IStream *stream;
1088 CLSID clsid;
1089 HANDLE thread;
1090 DWORD tid;
1092 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1093 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1095 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1097 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
1098 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
1099 ok_ole_success(hr, "CoRegisterClassObject");
1101 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1102 ok_ole_success(hr, "CoRegisterPSClsid");
1104 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1105 ok_ole_success(hr, "CoGetPSClsid");
1106 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1107 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1109 thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid);
1110 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1111 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
1112 CloseHandle(thread);
1114 hr = CoGetPSClsid(&IID_TestPS, &clsid);
1115 ok_ole_success(hr, "CoGetPSClsid");
1116 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1117 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1119 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1120 ok_ole_success(hr, "CreateStreamOnHGlobal");
1122 SET_EXPECT(CreateStub);
1123 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1124 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1125 CHECK_CALLED(CreateStub);
1127 hr = CoGetPSClsid(&IID_IEnumOLEVERB, &clsid);
1128 ok_ole_success(hr, "CoGetPSClsid");
1130 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void **)&ps_factory_buffer);
1131 ok_ole_success(hr, "CoGetClassObject");
1133 hr = CoRegisterPSClsid(&IID_IEnumOLEVERB, &CLSID_WineTestPSFactoryBuffer);
1134 ok_ole_success(hr, "CoRegisterPSClsid");
1136 SET_EXPECT(CreateStub);
1137 hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1138 ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
1139 CHECK_CALLED(CreateStub);
1141 hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1142 ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
1144 IStream_Release(stream);
1145 IPSFactoryBuffer_Release(ps_factory_buffer);
1146 ps_factory_buffer = NULL;
1148 hr = CoRevokeClassObject(dwRegistrationKey);
1149 ok_ole_success(hr, "CoRevokeClassObject");
1151 CoUninitialize();
1153 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1155 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1156 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
1158 hr = CoGetPSClsid(&IID_TestPS, &clsid);
1159 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
1161 CoUninitialize();
1163 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1165 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1166 ok_ole_success(hr, "CoRegisterPSClsid");
1168 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1169 ok_ole_success(hr, "CoGetPSClsid");
1170 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1171 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1173 thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid);
1174 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1175 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
1176 CloseHandle(thread);
1178 hr = CoGetPSClsid(&IID_TestPS, &clsid);
1179 ok_ole_success(hr, "CoGetPSClsid");
1180 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1181 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1183 CoUninitialize();
1186 static void test_CoGetPSClsid(void)
1188 ULONG_PTR cookie;
1189 HANDLE handle;
1190 HRESULT hr;
1191 CLSID clsid;
1192 HKEY hkey;
1193 LONG res;
1194 const BOOL is_win64 = (sizeof(void*) != sizeof(int));
1195 BOOL is_wow64 = FALSE;
1197 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1198 ok(hr == CO_E_NOTINITIALIZED,
1199 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
1200 hr);
1202 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1204 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1205 ok_ole_success(hr, "CoGetPSClsid");
1207 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1208 ok(hr == REGDB_E_IIDNOTREG,
1209 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
1210 hr);
1212 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
1213 ok(hr == E_INVALIDARG,
1214 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
1215 hr);
1217 if (!pRegOverridePredefKey)
1219 win_skip("RegOverridePredefKey not available\n");
1220 CoUninitialize();
1221 return;
1223 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1224 ok_ole_success(hr, "CoGetPSClsid");
1226 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
1227 KEY_ALL_ACCESS, NULL, &hkey, NULL);
1228 ok(!res, "RegCreateKeyEx returned %d\n", res);
1230 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
1231 ok(!res, "RegOverridePredefKey returned %d\n", res);
1233 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1234 ok_ole_success(hr, "CoGetPSClsid");
1236 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
1237 ok(!res, "RegOverridePredefKey returned %d\n", res);
1239 RegCloseKey(hkey);
1241 /* not registered CLSID */
1242 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1243 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1245 if ((handle = activate_context(actctx_manifest, &cookie)))
1247 memset(&clsid, 0, sizeof(clsid));
1248 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1249 ok(hr == S_OK, "got 0x%08x\n", hr);
1250 ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1252 memset(&clsid, 0, sizeof(clsid));
1253 hr = CoGetPSClsid(&IID_Testiface2, &clsid);
1254 ok(hr == S_OK, "got 0x%08x\n", hr);
1255 ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1257 memset(&clsid, 0, sizeof(clsid));
1258 hr = CoGetPSClsid(&IID_Testiface3, &clsid);
1259 ok(hr == S_OK, "got 0x%08x\n", hr);
1260 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1262 memset(&clsid, 0xaa, sizeof(clsid));
1263 hr = CoGetPSClsid(&IID_Testiface4, &clsid);
1264 ok(hr == S_OK, "got 0x%08x\n", hr);
1265 ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1267 /* register same interface and try to get CLSID back */
1268 hr = CoRegisterPSClsid(&IID_Testiface, &IID_Testiface4);
1269 ok(hr == S_OK, "got 0x%08x\n", hr);
1270 memset(&clsid, 0, sizeof(clsid));
1271 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1272 ok(hr == S_OK, "got 0x%08x\n", hr);
1273 ok(IsEqualGUID(&clsid, &IID_Testiface4), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1275 pDeactivateActCtx(0, cookie);
1276 pReleaseActCtx(handle);
1279 if (pRegDeleteKeyExA &&
1280 (is_win64 ||
1281 (pIsWow64Process && pIsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
1283 static GUID IID_DeadBeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1284 static const char clsidDeadBeef[] = "{deadbeef-dead-beef-dead-beefdeadbeef}";
1285 static const char clsidA[] = "{66666666-8888-7777-6666-555555555555}";
1286 HKEY hkey_iface, hkey_psclsid;
1287 REGSAM opposite = is_win64 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
1289 hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1290 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1292 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, "Interface",
1293 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_iface, NULL);
1294 ok(!res, "RegCreateKeyEx returned %d\n", res);
1295 res = RegCreateKeyExA(hkey_iface, clsidDeadBeef,
1296 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey, NULL);
1297 if (res == ERROR_ACCESS_DENIED)
1299 win_skip("Failed to create a key, skipping some of CoGetPSClsid() tests\n");
1300 goto cleanup;
1303 ok(!res, "RegCreateKeyEx returned %d\n", res);
1304 res = RegCreateKeyExA(hkey, "ProxyStubClsid32",
1305 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_psclsid, NULL);
1306 ok(!res, "RegCreateKeyEx returned %d\n", res);
1307 res = RegSetValueExA(hkey_psclsid, NULL, 0, REG_SZ, (const BYTE *)clsidA, strlen(clsidA)+1);
1308 ok(!res, "RegSetValueEx returned %d\n", res);
1309 RegCloseKey(hkey_psclsid);
1311 hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1312 ok_ole_success(hr, "CoGetPSClsid");
1313 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1315 res = pRegDeleteKeyExA(hkey, "ProxyStubClsid32", opposite, 0);
1316 ok(!res, "RegDeleteKeyEx returned %d\n", res);
1317 RegCloseKey(hkey);
1318 res = pRegDeleteKeyExA(hkey_iface, clsidDeadBeef, opposite, 0);
1319 ok(!res, "RegDeleteKeyEx returned %d\n", res);
1321 cleanup:
1322 RegCloseKey(hkey_iface);
1325 CoUninitialize();
1328 /* basic test, mainly for invalid arguments. see marshal.c for more */
1329 static void test_CoUnmarshalInterface(void)
1331 IUnknown *pProxy;
1332 IStream *pStream;
1333 HRESULT hr;
1335 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
1336 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1338 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1339 ok_ole_success(hr, "CreateStreamOnHGlobal");
1341 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1342 todo_wine
1343 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1345 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1347 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1348 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1350 CoUninitialize();
1352 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
1353 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1355 IStream_Release(pStream);
1358 static void test_CoGetInterfaceAndReleaseStream(void)
1360 HRESULT hr;
1361 IUnknown *pUnk;
1363 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1365 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
1366 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
1368 CoUninitialize();
1371 /* basic test, mainly for invalid arguments. see marshal.c for more */
1372 static void test_CoMarshalInterface(void)
1374 IStream *pStream;
1375 HRESULT hr;
1376 static const LARGE_INTEGER llZero;
1378 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1380 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1381 ok_ole_success(hr, "CreateStreamOnHGlobal");
1383 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1384 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1386 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1387 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1389 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1390 ok_ole_success(hr, "CoMarshalInterface");
1392 /* stream not rewound */
1393 hr = CoReleaseMarshalData(pStream);
1394 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1396 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1397 ok_ole_success(hr, "IStream_Seek");
1399 hr = CoReleaseMarshalData(pStream);
1400 ok_ole_success(hr, "CoReleaseMarshalData");
1402 IStream_Release(pStream);
1404 CoUninitialize();
1407 static void test_CoMarshalInterThreadInterfaceInStream(void)
1409 IStream *pStream;
1410 HRESULT hr;
1411 IClassFactory *pProxy;
1413 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1415 cLocks = 0;
1417 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
1418 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1420 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
1421 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1423 ok_no_locks();
1425 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
1426 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
1428 ok_more_than_one_lock();
1430 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1431 ok_ole_success(hr, "CoUnmarshalInterface");
1433 IClassFactory_Release(pProxy);
1434 IStream_Release(pStream);
1436 ok_no_locks();
1438 CoUninitialize();
1441 static void test_CoRegisterClassObject(void)
1443 ULONG_PTR ctxcookie;
1444 HANDLE handle;
1445 DWORD cookie;
1446 HRESULT hr;
1447 IClassFactory *pcf;
1449 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1451 /* CLSCTX_INPROC_SERVER */
1452 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1453 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1454 ok_ole_success(hr, "CoRegisterClassObject");
1455 hr = CoRevokeClassObject(cookie);
1456 ok_ole_success(hr, "CoRevokeClassObject");
1458 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1459 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1460 ok_ole_success(hr, "CoRegisterClassObject");
1461 hr = CoRevokeClassObject(cookie);
1462 ok_ole_success(hr, "CoRevokeClassObject");
1464 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1465 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1466 ok_ole_success(hr, "CoRegisterClassObject");
1467 hr = CoRevokeClassObject(cookie);
1468 ok_ole_success(hr, "CoRevokeClassObject");
1470 /* CLSCTX_LOCAL_SERVER */
1471 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1472 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1473 ok_ole_success(hr, "CoRegisterClassObject");
1474 hr = CoRevokeClassObject(cookie);
1475 ok_ole_success(hr, "CoRevokeClassObject");
1477 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1478 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1479 ok_ole_success(hr, "CoRegisterClassObject");
1480 hr = CoRevokeClassObject(cookie);
1481 ok_ole_success(hr, "CoRevokeClassObject");
1483 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1484 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1485 ok_ole_success(hr, "CoRegisterClassObject");
1486 hr = CoRevokeClassObject(cookie);
1487 ok_ole_success(hr, "CoRevokeClassObject");
1489 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
1490 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1491 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1492 ok_ole_success(hr, "CoRegisterClassObject");
1493 hr = CoRevokeClassObject(cookie);
1494 ok_ole_success(hr, "CoRevokeClassObject");
1496 /* test whether an object that doesn't support IClassFactory can be
1497 * registered for CLSCTX_LOCAL_SERVER */
1498 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
1499 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1500 ok_ole_success(hr, "CoRegisterClassObject");
1501 hr = CoRevokeClassObject(cookie);
1502 ok_ole_success(hr, "CoRevokeClassObject");
1504 /* test whether registered class becomes invalid when apartment is destroyed */
1505 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1506 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1507 ok_ole_success(hr, "CoRegisterClassObject");
1509 CoUninitialize();
1510 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1512 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
1513 &IID_IClassFactory, (void **)&pcf);
1514 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
1516 /* crashes with at least win9x DCOM! */
1517 if (0)
1518 CoRevokeClassObject(cookie);
1520 /* test that object is accessible */
1521 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER,
1522 REGCLS_MULTIPLEUSE, &cookie);
1523 ok(hr == S_OK, "got 0x%08x\n", hr);
1525 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1526 ok(hr == S_OK, "got 0x%08x\n", hr);
1527 IClassFactory_Release(pcf);
1529 /* context now contains CLSID_WineOOPTest, test if registered one could still be used */
1530 if ((handle = activate_context(actctx_manifest, &ctxcookie)))
1532 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1533 todo_wine
1534 ok(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), "got 0x%08x\n", hr);
1536 pDeactivateActCtx(0, ctxcookie);
1537 pReleaseActCtx(handle);
1540 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1541 ok(hr == S_OK, "got 0x%08x\n", hr);
1542 IClassFactory_Release(pcf);
1544 hr = CoRevokeClassObject(cookie);
1545 ok(hr == S_OK, "got 0x%08x\n", hr);
1547 CoUninitialize();
1550 static HRESULT get_class_object(CLSCTX clsctx)
1552 HRESULT hr;
1553 IClassFactory *pcf;
1555 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1556 (void **)&pcf);
1558 if (SUCCEEDED(hr))
1559 IClassFactory_Release(pcf);
1561 return hr;
1564 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1566 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1567 HRESULT hr;
1569 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1571 hr = get_class_object(clsctx);
1573 CoUninitialize();
1575 return hr;
1578 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1580 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1581 HRESULT hr;
1582 IClassFactory *pcf;
1583 IMultiQI *pMQI;
1585 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1587 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1588 (void **)&pcf);
1590 if (SUCCEEDED(hr))
1592 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1593 if (SUCCEEDED(hr))
1594 IMultiQI_Release(pMQI);
1595 IClassFactory_Release(pcf);
1598 CoUninitialize();
1600 return hr;
1603 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1605 HRESULT hr;
1606 DWORD cookie;
1608 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1610 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1611 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1613 CoUninitialize();
1615 return hr;
1618 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1620 DWORD cookie = (DWORD_PTR)pv;
1621 HRESULT hr;
1623 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1625 hr = CoRevokeClassObject(cookie);
1627 CoUninitialize();
1629 return hr;
1632 static void test_registered_object_thread_affinity(void)
1634 HRESULT hr;
1635 DWORD cookie;
1636 HANDLE thread;
1637 DWORD tid;
1638 DWORD exitcode;
1640 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1642 /* CLSCTX_INPROC_SERVER */
1644 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1645 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1646 ok_ole_success(hr, "CoRegisterClassObject");
1648 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1649 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1650 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1651 GetExitCodeThread(thread, &exitcode);
1652 hr = exitcode;
1653 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1654 "registered in different thread should return REGDB_E_CLASSNOTREG "
1655 "instead of 0x%08x\n", hr);
1657 hr = get_class_object(CLSCTX_INPROC_SERVER);
1658 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1659 "thread should return S_OK instead of 0x%08x\n", hr);
1661 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1662 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1663 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1664 GetExitCodeThread(thread, &exitcode);
1665 hr = exitcode;
1666 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1668 hr = CoRevokeClassObject(cookie);
1669 ok_ole_success(hr, "CoRevokeClassObject");
1671 /* CLSCTX_LOCAL_SERVER */
1673 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1674 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1675 ok_ole_success(hr, "CoRegisterClassObject");
1677 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1678 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1679 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1681 MSG msg;
1682 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1684 TranslateMessage(&msg);
1685 DispatchMessageA(&msg);
1688 GetExitCodeThread(thread, &exitcode);
1689 hr = exitcode;
1690 ok(hr == S_OK, "CoGetClassObject on local server object "
1691 "registered in different thread should return S_OK "
1692 "instead of 0x%08x\n", hr);
1694 hr = get_class_object(CLSCTX_LOCAL_SERVER);
1695 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1696 "thread should return S_OK instead of 0x%08x\n", hr);
1698 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid);
1699 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1700 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1701 GetExitCodeThread(thread, &exitcode);
1702 hr = exitcode;
1703 ok(hr == RPC_E_WRONG_THREAD || broken(hr == S_OK) /* win8 */, "CoRevokeClassObject called from different "
1704 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1706 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1707 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1708 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1709 GetExitCodeThread(thread, &exitcode);
1710 hr = exitcode;
1711 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1712 "thread should return S_OK instead of 0x%08x\n", hr);
1714 hr = CoRevokeClassObject(cookie);
1715 ok_ole_success(hr, "CoRevokeClassObject");
1717 CoUninitialize();
1720 static DWORD CALLBACK free_libraries_thread(LPVOID p)
1722 CoFreeUnusedLibraries();
1723 return 0;
1726 static inline BOOL is_module_loaded(const char *module)
1728 return GetModuleHandleA(module) != 0;
1731 static void test_CoFreeUnusedLibraries(void)
1733 HRESULT hr;
1734 IUnknown *pUnk;
1735 DWORD tid;
1736 HANDLE thread;
1738 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1740 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1742 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1743 if (hr == REGDB_E_CLASSNOTREG)
1745 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1746 CoUninitialize();
1747 return;
1749 ok_ole_success(hr, "CoCreateInstance");
1751 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1753 ok(pUnk != NULL ||
1754 broken(pUnk == NULL), /* win9x */
1755 "Expected a valid pointer\n");
1756 if (pUnk)
1757 IUnknown_Release(pUnk);
1759 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1761 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1762 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1763 CloseHandle(thread);
1765 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1767 CoFreeUnusedLibraries();
1769 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1771 CoUninitialize();
1774 static void test_CoGetObjectContext(void)
1776 HRESULT hr;
1777 ULONG refs;
1778 IComThreadingInfo *pComThreadingInfo, *threadinginfo2;
1779 IContextCallback *pContextCallback;
1780 IObjContext *pObjContext;
1781 APTTYPE apttype;
1782 THDTYPE thdtype;
1783 GUID id, id2;
1785 if (!pCoGetObjectContext)
1787 win_skip("CoGetObjectContext not present\n");
1788 return;
1791 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1792 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1793 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1795 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1797 test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE);
1799 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1800 ok_ole_success(hr, "CoGetObjectContext");
1802 threadinginfo2 = NULL;
1803 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&threadinginfo2);
1804 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1805 ok(pComThreadingInfo == threadinginfo2, "got different instance\n");
1806 IComThreadingInfo_Release(threadinginfo2);
1808 hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, NULL);
1809 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1811 id = id2 = GUID_NULL;
1812 hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, &id);
1813 ok(hr == S_OK, "got 0x%08x\n", hr);
1815 hr = CoGetCurrentLogicalThreadId(&id2);
1816 ok(IsEqualGUID(&id, &id2), "got %s, expected %s\n", wine_dbgstr_guid(&id), wine_dbgstr_guid(&id2));
1818 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1819 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1820 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1822 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1823 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1824 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1826 refs = IComThreadingInfo_Release(pComThreadingInfo);
1827 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1829 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1830 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1832 refs = IContextCallback_Release(pContextCallback);
1833 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1835 CoUninitialize();
1837 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1839 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1840 ok_ole_success(hr, "CoGetObjectContext");
1842 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1843 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1844 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1846 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1847 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1848 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1850 refs = IComThreadingInfo_Release(pComThreadingInfo);
1851 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1853 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1854 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1856 refs = IContextCallback_Release(pContextCallback);
1857 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1859 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1860 ok_ole_success(hr, "CoGetObjectContext");
1862 refs = IObjContext_Release(pObjContext);
1863 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
1865 CoUninitialize();
1868 typedef struct {
1869 IUnknown IUnknown_iface;
1870 LONG refs;
1871 } Test_CallContext;
1873 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
1875 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
1878 static HRESULT WINAPI Test_CallContext_QueryInterface(
1879 IUnknown *iface,
1880 REFIID riid,
1881 LPVOID *ppvObj)
1883 if (ppvObj == NULL) return E_POINTER;
1885 if (IsEqualGUID(riid, &IID_IUnknown))
1887 *ppvObj = iface;
1888 IUnknown_AddRef(iface);
1889 return S_OK;
1892 *ppvObj = NULL;
1893 return E_NOINTERFACE;
1896 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
1898 Test_CallContext *This = impl_from_IUnknown(iface);
1899 return InterlockedIncrement(&This->refs);
1902 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
1904 Test_CallContext *This = impl_from_IUnknown(iface);
1905 ULONG refs = InterlockedDecrement(&This->refs);
1906 if (!refs)
1907 HeapFree(GetProcessHeap(), 0, This);
1908 return refs;
1911 static const IUnknownVtbl TestCallContext_Vtbl =
1913 Test_CallContext_QueryInterface,
1914 Test_CallContext_AddRef,
1915 Test_CallContext_Release
1918 static void test_CoGetCallContext(void)
1920 HRESULT hr;
1921 ULONG refs;
1922 IUnknown *pUnk;
1923 Test_CallContext *test_object;
1925 if (!pCoSwitchCallContext)
1927 skip("CoSwitchCallContext not present\n");
1928 return;
1931 CoInitialize(NULL);
1933 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
1934 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
1935 test_object->refs = 1;
1937 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1938 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1940 pUnk = (IUnknown*)0xdeadbeef;
1941 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
1942 ok_ole_success(hr, "CoSwitchCallContext");
1943 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
1944 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1945 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1946 IUnknown_Release(&test_object->IUnknown_iface);
1948 pUnk = (IUnknown*)0xdeadbeef;
1949 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1950 ok_ole_success(hr, "CoGetCallContext");
1951 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1952 &test_object->IUnknown_iface, pUnk);
1953 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1954 ok(refs == 3, "Expected refcount 3, got %d\n", refs);
1955 IUnknown_Release(&test_object->IUnknown_iface);
1956 IUnknown_Release(pUnk);
1958 pUnk = (IUnknown*)0xdeadbeef;
1959 hr = pCoSwitchCallContext(NULL, &pUnk);
1960 ok_ole_success(hr, "CoSwitchCallContext");
1961 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1962 &test_object->IUnknown_iface, pUnk);
1963 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1964 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1965 IUnknown_Release(&test_object->IUnknown_iface);
1967 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1968 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1970 IUnknown_Release(&test_object->IUnknown_iface);
1972 CoUninitialize();
1975 static void test_CoGetContextToken(void)
1977 HRESULT hr;
1978 ULONG refs;
1979 ULONG_PTR token, token2;
1980 IObjContext *ctx;
1982 if (!pCoGetContextToken)
1984 win_skip("CoGetContextToken not present\n");
1985 return;
1988 token = 0xdeadbeef;
1989 hr = pCoGetContextToken(&token);
1990 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
1991 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
1993 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
1995 CoInitialize(NULL);
1997 test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE);
1999 hr = pCoGetContextToken(NULL);
2000 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
2002 token = 0;
2003 hr = pCoGetContextToken(&token);
2004 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2005 ok(token, "Expected token != 0\n");
2007 token2 = 0;
2008 hr = pCoGetContextToken(&token2);
2009 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2010 ok(token2 == token, "got different token\n");
2012 refs = IUnknown_AddRef((IUnknown *)token);
2013 ok(refs == 1, "Expected 1, got %u\n", refs);
2015 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
2016 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2017 ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
2019 refs = IObjContext_AddRef(ctx);
2020 ok(refs == 3, "Expected 3, got %u\n", refs);
2022 refs = IObjContext_Release(ctx);
2023 ok(refs == 2, "Expected 2, got %u\n", refs);
2025 refs = IUnknown_Release((IUnknown *)token);
2026 ok(refs == 1, "Expected 1, got %u\n", refs);
2028 /* CoGetContextToken does not add a reference */
2029 token = 0;
2030 hr = pCoGetContextToken(&token);
2031 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2032 ok(token, "Expected token != 0\n");
2033 ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
2035 refs = IObjContext_AddRef(ctx);
2036 ok(refs == 2, "Expected 1, got %u\n", refs);
2038 refs = IObjContext_Release(ctx);
2039 ok(refs == 1, "Expected 0, got %u\n", refs);
2041 refs = IObjContext_Release(ctx);
2042 ok(refs == 0, "Expected 0, got %u\n", refs);
2044 CoUninitialize();
2047 static void test_TreatAsClass(void)
2049 HRESULT hr;
2050 CLSID out;
2051 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
2052 static const char deadbeefA[] = "{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}";
2053 IInternetProtocol *pIP = NULL;
2054 HKEY clsidkey, deadbeefkey;
2055 LONG lr;
2057 if (!pCoGetTreatAsClass)
2059 win_skip("CoGetTreatAsClass not present\n");
2060 return;
2063 hr = pCoGetTreatAsClass(&deadbeef,&out);
2064 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
2065 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
2067 hr = pCoGetTreatAsClass(NULL, &out);
2068 ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr);
2069 ok(IsEqualGUID(&out, &deadbeef), "expected no change to the clsid\n");
2071 hr = pCoGetTreatAsClass(&deadbeef, NULL);
2072 ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr);
2074 lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &clsidkey);
2075 ok(!lr, "Couldn't open CLSID key, error %d\n", lr);
2077 lr = RegCreateKeyExA(clsidkey, deadbeefA, 0, NULL, 0, KEY_WRITE, NULL, &deadbeefkey, NULL);
2078 if (lr) {
2079 win_skip("CoGetTreatAsClass() tests will be skipped (failed to create a test key, error %d)\n", lr);
2080 RegCloseKey(clsidkey);
2081 return;
2084 hr = pCoTreatAsClass(&deadbeef, &deadbeef);
2085 ok(hr == REGDB_E_WRITEREGDB, "CoTreatAsClass gave wrong error: %08x\n", hr);
2087 hr = pCoTreatAsClass(&deadbeef, &CLSID_FileProtocol);
2088 if(hr == REGDB_E_WRITEREGDB){
2089 win_skip("Insufficient privileges to use CoTreatAsClass\n");
2090 goto exit;
2092 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
2094 hr = pCoGetTreatAsClass(&deadbeef, &out);
2095 ok(hr == S_OK, "CoGetTreatAsClass failed: %08x\n",hr);
2096 ok(IsEqualGUID(&out, &CLSID_FileProtocol), "expected to get substituted clsid\n");
2098 OleInitialize(NULL);
2100 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2101 if(hr == REGDB_E_CLASSNOTREG)
2103 win_skip("IE not installed so can't test CoCreateInstance\n");
2104 goto exit;
2107 ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
2108 if(pIP){
2109 IInternetProtocol_Release(pIP);
2110 pIP = NULL;
2113 hr = pCoTreatAsClass(&deadbeef, &CLSID_NULL);
2114 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
2116 hr = pCoGetTreatAsClass(&deadbeef, &out);
2117 ok(hr == S_FALSE, "expected S_FALSE got %08x\n", hr);
2118 ok(IsEqualGUID(&out, &deadbeef), "expected to get same clsid back\n");
2120 /* bizarrely, native's CoTreatAsClass takes some time to take effect in CoCreateInstance */
2121 Sleep(200);
2123 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2124 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance gave wrong error: %08x\n", hr);
2126 if(pIP)
2127 IInternetProtocol_Release(pIP);
2129 exit:
2130 OleUninitialize();
2131 RegCloseKey(deadbeefkey);
2132 RegDeleteKeyA(clsidkey, deadbeefA);
2133 RegCloseKey(clsidkey);
2136 static void test_CoInitializeEx(void)
2138 HRESULT hr;
2140 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2141 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2143 /* Calling OleInitialize for the first time should yield S_OK even with
2144 * apartment already initialized by previous CoInitialize(Ex) calls. */
2145 hr = OleInitialize(NULL);
2146 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
2148 /* Subsequent calls to OleInitialize should return S_FALSE */
2149 hr = OleInitialize(NULL);
2150 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
2152 /* Cleanup */
2153 CoUninitialize();
2154 OleUninitialize();
2155 OleUninitialize();
2158 static void test_OleInitialize_InitCounting(void)
2160 HRESULT hr;
2161 IUnknown *pUnk;
2162 REFCLSID rclsid = &CLSID_InternetZoneManager;
2164 /* 1. OleInitialize fails but OleUninitialize is still called: apartment stays initialized */
2165 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
2166 ok(hr == S_OK, "CoInitializeEx(COINIT_MULTITHREADED) failed with error 0x%08x\n", hr);
2168 hr = OleInitialize(NULL);
2169 ok(hr == RPC_E_CHANGED_MODE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", RPC_E_CHANGED_MODE, hr);
2170 OleUninitialize();
2172 pUnk = (IUnknown *)0xdeadbeef;
2173 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2174 ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2175 if (pUnk) IUnknown_Release(pUnk);
2177 CoUninitialize();
2179 /* 2. Extra multiple OleUninitialize: apartment stays initialized until CoUninitialize */
2180 hr = CoInitialize(NULL);
2181 ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
2183 hr = OleInitialize(NULL);
2184 ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2185 OleUninitialize();
2186 OleUninitialize();
2187 OleUninitialize();
2189 pUnk = (IUnknown *)0xdeadbeef;
2190 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2191 ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2192 if (pUnk) IUnknown_Release(pUnk);
2194 CoUninitialize();
2196 pUnk = (IUnknown *)0xdeadbeef;
2197 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2198 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
2199 if (pUnk) IUnknown_Release(pUnk);
2201 /* 3. CoUninitialize does not formally deinit Ole */
2202 hr = CoInitialize(NULL);
2203 ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
2205 hr = OleInitialize(NULL);
2206 ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2208 CoUninitialize();
2209 CoUninitialize();
2211 pUnk = (IUnknown *)0xdeadbeef;
2212 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2213 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
2214 /* COM is not initialized anymore */
2215 if (pUnk) IUnknown_Release(pUnk);
2217 hr = OleInitialize(NULL);
2218 ok(hr == S_FALSE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_FALSE, hr);
2219 /* ... but native OleInit returns S_FALSE as if Ole is considered initialized */
2221 OleUninitialize();
2225 static void test_OleRegGetMiscStatus(void)
2227 ULONG_PTR cookie;
2228 HANDLE handle;
2229 DWORD status;
2230 HRESULT hr;
2232 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, NULL);
2233 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2235 status = 0xdeadbeef;
2236 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2237 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
2238 ok(status == 0, "got 0x%08x\n", status);
2240 status = -1;
2241 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2242 ok(hr == S_OK, "got 0x%08x\n", hr);
2243 ok(status == 0, "got 0x%08x\n", status);
2245 if ((handle = activate_context(actctx_manifest, &cookie)))
2247 status = 0;
2248 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2249 ok(hr == S_OK, "got 0x%08x\n", hr);
2250 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2252 /* context data takes precedence over registration info */
2253 status = 0;
2254 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2255 ok(hr == S_OK, "got 0x%08x\n", hr);
2256 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2258 /* there's no such attribute in context */
2259 status = -1;
2260 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status);
2261 ok(hr == S_OK, "got 0x%08x\n", hr);
2262 ok(status == 0, "got 0x%08x\n", status);
2264 pDeactivateActCtx(0, cookie);
2265 pReleaseActCtx(handle);
2269 static void test_OleRegGetUserType(void)
2271 static const WCHAR stdfont_usertypeW[] = {'S','t','a','n','d','a','r','d',' ','F','o','n','t',0};
2272 static const WCHAR stdfont2_usertypeW[] = {'C','L','S','I','D','_','S','t','d','F','o','n','t',0};
2273 static const WCHAR clsidkeyW[] = {'C','L','S','I','D',0};
2274 static const WCHAR defvalueW[] = {'D','e','f','a','u','l','t',' ','N','a','m','e',0};
2275 static const WCHAR auxvalue0W[] = {'A','u','x',' ','N','a','m','e',' ','0',0};
2276 static const WCHAR auxvalue2W[] = {'A','u','x',' ','N','a','m','e',' ','2',0};
2277 static const WCHAR auxvalue3W[] = {'A','u','x',' ','N','a','m','e',' ','3',0};
2278 static const WCHAR auxvalue4W[] = {'A','u','x',' ','N','a','m','e',' ','4',0};
2280 static const char auxvalues[][16] = {
2281 "Aux Name 0",
2282 "Aux Name 1",
2283 "Aux Name 2",
2284 "Aux Name 3",
2285 "Aux Name 4"
2288 HKEY clsidhkey, hkey, auxhkey, classkey;
2289 DWORD form, ret, disposition;
2290 WCHAR clsidW[39];
2291 ULONG_PTR cookie;
2292 HANDLE handle;
2293 HRESULT hr;
2294 WCHAR *str;
2295 int i;
2297 for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) {
2298 hr = OleRegGetUserType(&CLSID_Testclass, form, NULL);
2299 ok(hr == E_INVALIDARG, "form %u: got 0x%08x\n", form, hr);
2301 str = (void*)0xdeadbeef;
2302 hr = OleRegGetUserType(&CLSID_Testclass, form, &str);
2303 ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr);
2304 ok(str == NULL, "form %u: got %p\n", form, str);
2306 /* same string returned for StdFont for all form types */
2307 str = NULL;
2308 hr = OleRegGetUserType(&CLSID_StdFont, form, &str);
2309 ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr);
2310 ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */,
2311 "form %u, got %s\n", form, wine_dbgstr_w(str));
2312 CoTaskMemFree(str);
2315 if ((handle = activate_context(actctx_manifest, &cookie)))
2317 for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) {
2318 str = (void*)0xdeadbeef;
2319 hr = OleRegGetUserType(&CLSID_Testclass, form, &str);
2320 ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr);
2321 ok(str == NULL, "form %u: got %s\n", form, wine_dbgstr_w(str));
2323 /* same string returned for StdFont for all form types */
2324 str = NULL;
2325 hr = OleRegGetUserType(&CLSID_StdFont, form, &str);
2326 ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr);
2327 ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */,
2328 "form %u, got %s\n", form, wine_dbgstr_w(str));
2329 CoTaskMemFree(str);
2332 pDeactivateActCtx(0, cookie);
2333 pReleaseActCtx(handle);
2336 /* test using registered CLSID */
2337 StringFromGUID2(&CLSID_non_existent, clsidW, ARRAY_SIZE(clsidW));
2339 ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsidkeyW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &clsidhkey, &disposition);
2340 if (!ret)
2342 ret = RegCreateKeyExW(clsidhkey, clsidW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &classkey, NULL);
2343 if (ret)
2344 RegCloseKey(clsidhkey);
2347 if (ret == ERROR_ACCESS_DENIED)
2349 win_skip("Failed to create test key, skipping some of OleRegGetUserType() tests.\n");
2350 return;
2353 ok(!ret, "failed to create a key, error %d\n", ret);
2355 ret = RegSetValueExW(classkey, NULL, 0, REG_SZ, (const BYTE*)defvalueW, sizeof(defvalueW));
2356 ok(!ret, "got error %d\n", ret);
2358 ret = RegCreateKeyExA(classkey, "AuxUserType", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &auxhkey, NULL);
2359 ok(!ret, "got error %d\n", ret);
2361 /* populate AuxUserType */
2362 for (i = 0; i <= 4; i++) {
2363 char name[16];
2365 sprintf(name, "AuxUserType\\%d", i);
2366 ret = RegCreateKeyExA(classkey, name, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2367 ok(!ret, "got error %d\n", ret);
2369 ret = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE*)auxvalues[i], strlen(auxvalues[i]));
2370 ok(!ret, "got error %d\n", ret);
2371 RegCloseKey(hkey);
2374 str = NULL;
2375 hr = OleRegGetUserType(&CLSID_non_existent, 0, &str);
2376 ok(hr == S_OK, "got 0x%08x\n", hr);
2377 ok(!lstrcmpW(str, auxvalue0W), "got %s\n", wine_dbgstr_w(str));
2378 CoTaskMemFree(str);
2380 str = NULL;
2381 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_FULL, &str);
2382 ok(hr == S_OK, "got 0x%08x\n", hr);
2383 ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str));
2384 CoTaskMemFree(str);
2386 str = NULL;
2387 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_SHORT, &str);
2388 ok(hr == S_OK, "got 0x%08x\n", hr);
2389 ok(!lstrcmpW(str, auxvalue2W), "got %s\n", wine_dbgstr_w(str));
2390 CoTaskMemFree(str);
2392 str = NULL;
2393 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME, &str);
2394 ok(hr == S_OK, "got 0x%08x\n", hr);
2395 ok(!lstrcmpW(str, auxvalue3W), "got %s\n", wine_dbgstr_w(str));
2396 CoTaskMemFree(str);
2398 str = NULL;
2399 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+1, &str);
2400 ok(hr == S_OK, "got 0x%08x\n", hr);
2401 ok(!lstrcmpW(str, auxvalue4W), "got %s\n", wine_dbgstr_w(str));
2402 CoTaskMemFree(str);
2404 str = NULL;
2405 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+2, &str);
2406 ok(hr == S_OK, "got 0x%08x\n", hr);
2407 ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str));
2408 CoTaskMemFree(str);
2410 /* registry cleanup */
2411 for (i = 0; i <= 4; i++)
2413 char name[2];
2414 sprintf(name, "%d", i);
2415 RegDeleteKeyA(auxhkey, name);
2417 RegCloseKey(auxhkey);
2418 RegDeleteKeyA(classkey, "AuxUserType");
2419 RegCloseKey(classkey);
2420 RegDeleteKeyW(clsidhkey, clsidW);
2421 RegCloseKey(clsidhkey);
2422 if (disposition == REG_CREATED_NEW_KEY)
2423 RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID");
2426 static void test_CoCreateGuid(void)
2428 HRESULT hr;
2430 hr = CoCreateGuid(NULL);
2431 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2434 static void CALLBACK apc_test_proc(ULONG_PTR param)
2436 /* nothing */
2439 static DWORD CALLBACK release_semaphore_thread( LPVOID arg )
2441 HANDLE handle = arg;
2442 if (WaitForSingleObject(handle, 200) == WAIT_TIMEOUT)
2443 ReleaseSemaphore(handle, 1, NULL);
2444 return 0;
2447 static DWORD CALLBACK send_message_thread(LPVOID arg)
2449 HWND hWnd = arg;
2450 Sleep(50);
2451 SendMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2452 return 0;
2455 static DWORD CALLBACK send_and_post_user_message_thread(void *arg)
2457 HWND hwnd = arg;
2458 Sleep(30);
2459 SendMessageA(hwnd, WM_USER, 0, 0);
2460 PostMessageA(hwnd, WM_USER, 0, 0);
2461 return 0;
2464 static DWORD CALLBACK post_message_thread(LPVOID arg)
2466 HWND hWnd = arg;
2467 Sleep(50);
2468 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2469 return 0;
2472 static const char cls_name[] = "cowait_test_class";
2474 static UINT cowait_msgs[100], cowait_msgs_first, cowait_msgs_last;
2476 static void cowait_msgs_reset(void)
2478 cowait_msgs_first = cowait_msgs_last = 0;
2481 #define cowait_msgs_expect_empty() _cowait_msgs_expect_empty(__LINE__)
2482 static void _cowait_msgs_expect_empty(unsigned line)
2484 while(cowait_msgs_first < cowait_msgs_last) {
2485 ok_(__FILE__,line)(0, "unexpected message %u\n", cowait_msgs[cowait_msgs_first]);
2486 cowait_msgs_first++;
2488 cowait_msgs_reset();
2491 #define cowait_msgs_expect_notified(a) _cowait_msgs_expect_notified(__LINE__,a)
2492 static void _cowait_msgs_expect_notified(unsigned line, UINT expected_msg)
2494 if(cowait_msgs_first == cowait_msgs_last) {
2495 ok_(__FILE__,line)(0, "expected message %u, received none\n", expected_msg);
2496 }else {
2497 ok_(__FILE__,line)(cowait_msgs[cowait_msgs_first] == expected_msg,
2498 "expected message %u, received %u \n",
2499 expected_msg, cowait_msgs[cowait_msgs_first]);
2500 cowait_msgs_first++;
2504 #define cowait_msgs_expect_queued(a,b) _cowait_msgs_expect_queued(__LINE__,a,b)
2505 static void _cowait_msgs_expect_queued(unsigned line, HWND hwnd, UINT expected_msg)
2507 MSG msg;
2508 BOOL success;
2510 success = PeekMessageA(&msg, hwnd, expected_msg, expected_msg, PM_REMOVE);
2511 ok_(__FILE__,line)(success, "PeekMessageA failed: %u\n", GetLastError());
2512 if(success)
2513 ok_(__FILE__,line)(msg.message == expected_msg, "unexpected message %u, expected %u\n",
2514 msg.message, expected_msg);
2517 static void flush_messages(void)
2519 MSG msg;
2520 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ));
2523 static LRESULT CALLBACK cowait_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
2525 if(cowait_msgs_last < ARRAY_SIZE(cowait_msgs))
2526 cowait_msgs[cowait_msgs_last++] = msg;
2527 if(msg == WM_DDE_FIRST)
2528 return 6;
2529 return DefWindowProcA(hwnd, msg, wparam, lparam);
2532 static DWORD CALLBACK cowait_unmarshal_thread(void *arg)
2534 IStream *stream = arg;
2535 IEnumOLEVERB *enum_verb;
2536 LARGE_INTEGER zero;
2537 IUnknown *unk;
2538 HRESULT hr;
2540 CoInitialize(NULL);
2542 zero.QuadPart = 0;
2543 hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2544 ok(hr == S_OK, "Seek failed: %08x\n", hr);
2546 hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk);
2547 ok(hr == S_OK, "CoUnmarshalInterface failed: %08x\n", hr);
2549 hr = IUnknown_QueryInterface(unk, &IID_IEnumOLEVERB, (void**)&enum_verb);
2550 ok(hr == S_OK, "QueryInterface failed: %08x\n", hr);
2552 IEnumOLEVERB_Release(enum_verb);
2553 IUnknown_Release(unk);
2555 CoUninitialize();
2556 return 0;
2559 static DWORD CALLBACK test_CoWaitForMultipleHandles_thread(LPVOID arg)
2561 HANDLE *handles = arg, event, thread;
2562 IStream *stream;
2563 BOOL success;
2564 DWORD index, tid;
2565 HRESULT hr;
2566 HWND hWnd;
2567 UINT uMSG = 0xc065;
2568 MSG msg;
2569 int ret;
2571 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2572 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2574 hWnd = CreateWindowExA(0, cls_name, "Test (thread)", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2575 ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
2577 index = 0xdeadbeef;
2578 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2579 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2580 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2581 ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index);
2582 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2583 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2585 index = 0xdeadbeef;
2586 PostMessageA(hWnd, WM_USER, 0, 0);
2587 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2588 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2589 ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index);
2590 success = PeekMessageA(&msg, hWnd, WM_USER, WM_USER, PM_REMOVE);
2591 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2593 /* Even if CoWaitForMultipleHandles does not pump a message it peeks
2594 * at ALL of them */
2595 index = 0xdeadbeef;
2596 PostMessageA(NULL, uMSG, 0, 0);
2598 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2599 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2600 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2602 /* Make sure message was peeked at */
2603 ret = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE);
2604 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
2606 /* But not pumped */
2607 success = PeekMessageA(&msg, NULL, uMSG, uMSG, PM_REMOVE);
2608 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2610 DestroyWindow(hWnd);
2611 CoUninitialize();
2613 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2614 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2616 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2617 ok(hr == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hr);
2619 hr = CoMarshalInterface(stream, &IID_IUnknown, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2620 ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
2622 event = CreateEventW(NULL, TRUE, FALSE, NULL);
2624 PostQuitMessage(66);
2625 PostThreadMessageW(GetCurrentThreadId(), WM_QUIT, 0, 0);
2627 hr = CoRegisterMessageFilter(&MessageFilter, NULL);
2628 ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr);
2630 thread = CreateThread(NULL, 0, cowait_unmarshal_thread, stream, 0, &tid);
2631 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2632 hr = CoWaitForMultipleHandles(0, 50, 1, &event, &index);
2633 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2634 index = WaitForSingleObject(thread, 200);
2635 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2636 CloseHandle(thread);
2638 hr = CoRegisterMessageFilter(NULL, NULL);
2639 ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr);
2641 IStream_Release(stream);
2643 CloseHandle(event);
2644 CoUninitialize();
2645 return 0;
2648 static void test_CoWaitForMultipleHandles(void)
2650 HANDLE handles[2], thread;
2651 DWORD index, tid;
2652 WNDCLASSEXA wc;
2653 BOOL success;
2654 HRESULT hr;
2655 HWND hWnd;
2656 MSG msg;
2658 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2659 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2661 memset(&wc, 0, sizeof(wc));
2662 wc.cbSize = sizeof(wc);
2663 wc.style = CS_VREDRAW | CS_HREDRAW;
2664 wc.hInstance = GetModuleHandleA(0);
2665 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2666 wc.hbrBackground = NULL;
2667 wc.lpszClassName = cls_name;
2668 wc.lpfnWndProc = cowait_window_proc;
2669 success = RegisterClassExA(&wc) != 0;
2670 ok(success, "RegisterClassExA failed %u\n", GetLastError());
2672 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2673 ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
2674 handles[0] = CreateSemaphoreA(NULL, 1, 1, NULL);
2675 ok(handles[0] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2676 handles[1] = CreateSemaphoreA(NULL, 1, 1, NULL);
2677 ok(handles[1] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2679 /* test without flags */
2681 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2682 hr = CoWaitForMultipleHandles(0, 50, 0, handles, NULL);
2683 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2684 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2685 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2687 index = 0xdeadbeef;
2688 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2689 hr = CoWaitForMultipleHandles(0, 50, 0, NULL, &index);
2690 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2691 ok(index == 0, "expected index 0, got %u\n", index);
2692 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2693 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2695 index = 0xdeadbeef;
2696 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2697 hr = CoWaitForMultipleHandles(0, 50, 0, handles, &index);
2698 ok(hr == RPC_E_NO_SYNC, "expected RPC_E_NO_SYNC, got 0x%08x\n", hr);
2699 ok(index == 0, "expected index 0, got %u\n", index);
2700 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2701 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2703 index = 0xdeadbeef;
2704 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2705 hr = CoWaitForMultipleHandles(0, 50, 1, handles, &index);
2706 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2707 ok(index == 0, "expected index 0, got %u\n", index);
2708 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2709 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2711 index = 0xdeadbeef;
2712 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2713 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2714 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2715 ok(index == 1, "expected index 1, got %u\n", index);
2716 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2717 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
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 || broken(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 /* test PostMessageA/SendMessageA from a different thread */
2729 index = 0xdeadbeef;
2730 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2731 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2732 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2733 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2734 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2735 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2736 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2737 index = WaitForSingleObject(thread, 200);
2738 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2739 CloseHandle(thread);
2741 index = 0xdeadbeef;
2742 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2743 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2744 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2745 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2746 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2747 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2748 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2749 index = WaitForSingleObject(thread, 200);
2750 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2751 CloseHandle(thread);
2753 ReleaseSemaphore(handles[0], 1, NULL);
2754 ReleaseSemaphore(handles[1], 1, NULL);
2756 /* test with COWAIT_WAITALL */
2758 index = 0xdeadbeef;
2759 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2760 hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 50, 2, handles, &index);
2761 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2762 ok(index == 0, "expected index 0, got %u\n", index);
2763 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2764 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2766 index = 0xdeadbeef;
2767 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2768 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2769 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2770 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2771 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2772 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2774 ReleaseSemaphore(handles[0], 1, NULL);
2775 ReleaseSemaphore(handles[1], 1, NULL);
2777 /* test with COWAIT_ALERTABLE */
2779 index = 0xdeadbeef;
2780 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2781 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 1, handles, &index);
2782 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2783 ok(index == 0, "expected index 0, got %u\n", index);
2784 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2785 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2787 index = 0xdeadbeef;
2788 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2789 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2790 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2791 ok(index == 1, "expected index 1, got %u\n", index);
2792 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2793 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2795 index = 0xdeadbeef;
2796 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2797 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2798 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2799 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2800 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2801 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2803 index = 0xdeadbeef;
2804 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2805 success = QueueUserAPC(apc_test_proc, GetCurrentThread(), 0);
2806 ok(success, "QueueUserAPC failed %u\n", GetLastError());
2807 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2808 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2809 ok(index == WAIT_IO_COMPLETION, "expected index WAIT_IO_COMPLETION, got %u\n", index);
2810 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2811 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2813 /* test with COWAIT_INPUTAVAILABLE (semaphores are still locked) */
2815 index = 0xdeadbeef;
2816 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2817 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2818 ok(success, "PeekMessageA returned FALSE\n");
2819 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2820 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2821 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2822 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2823 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2825 index = 0xdeadbeef;
2826 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2827 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2828 ok(success, "PeekMessageA returned FALSE\n");
2829 thread = CreateThread(NULL, 0, release_semaphore_thread, handles[1], 0, &tid);
2830 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2831 hr = CoWaitForMultipleHandles(COWAIT_INPUTAVAILABLE, 50, 2, handles, &index);
2832 ok(hr == RPC_S_CALLPENDING || broken(hr == E_INVALIDARG) || broken(hr == S_OK) /* Win 8 */,
2833 "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2834 if (hr != S_OK) ReleaseSemaphore(handles[1], 1, NULL);
2835 ok(index == 0 || broken(index == 1) /* Win 8 */, "expected index 0, got %u\n", index);
2836 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2837 ok(!success || broken(success && hr == E_INVALIDARG),
2838 "CoWaitForMultipleHandles didn't pump any messages\n");
2839 index = WaitForSingleObject(thread, 200);
2840 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2841 CloseHandle(thread);
2843 cowait_msgs_reset();
2844 PostMessageA(hWnd, 0, 0, 0);
2845 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2846 PostMessageA(hWnd, WM_USER+1, 0, 0);
2847 PostMessageA(hWnd, WM_DDE_FIRST+1, 0, 0);
2848 thread = CreateThread(NULL, 0, send_and_post_user_message_thread, hWnd, 0, &tid);
2849 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2851 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2852 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2854 cowait_msgs_expect_notified(WM_DDE_FIRST);
2855 cowait_msgs_expect_notified(WM_DDE_FIRST+1);
2856 cowait_msgs_expect_notified(WM_USER);
2857 cowait_msgs_expect_empty();
2858 cowait_msgs_expect_queued(hWnd, WM_USER);
2859 cowait_msgs_expect_queued(hWnd, WM_USER+1);
2860 flush_messages();
2862 index = WaitForSingleObject(thread, 200);
2863 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2864 CloseHandle(thread);
2866 /* test behaviour of WM_QUIT (semaphores are still locked) */
2868 PostMessageA(hWnd, WM_QUIT, 40, 0);
2869 memset(&msg, 0, sizeof(msg));
2870 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2871 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2872 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2873 ok(msg.wParam == 40, "expected msg.wParam = 40, got %lu\n", msg.wParam);
2874 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2875 ok(!success, "PeekMessageA succeeded\n");
2877 cowait_msgs_reset();
2878 PostMessageA(hWnd, WM_QUIT, 40, 0);
2879 PostMessageA(hWnd, 0, 0, 0);
2880 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2881 PostMessageA(hWnd, WM_USER+1, 0, 0);
2882 PostMessageA(hWnd, WM_DDE_FIRST+1, 0, 0);
2883 thread = CreateThread(NULL, 0, send_and_post_user_message_thread, hWnd, 0, &tid);
2884 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2886 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2887 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2889 cowait_msgs_expect_notified(WM_DDE_FIRST);
2890 cowait_msgs_expect_notified(WM_DDE_FIRST+1);
2891 cowait_msgs_expect_notified(WM_USER);
2892 cowait_msgs_expect_empty();
2893 cowait_msgs_expect_queued(hWnd, WM_USER);
2894 flush_messages();
2896 index = WaitForSingleObject(thread, 200);
2897 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2898 CloseHandle(thread);
2900 index = 0xdeadbeef;
2901 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2902 PostMessageA(hWnd, WM_QUIT, 41, 0);
2903 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2904 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2905 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2906 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2907 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2908 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2909 todo_wine
2910 ok(success || broken(!success) /* Win 2000/XP/8 */, "PeekMessageA failed, error %u\n", GetLastError());
2911 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2912 ok(!success, "PeekMessageA succeeded\n");
2913 memset(&msg, 0, sizeof(msg));
2914 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2915 todo_wine
2916 ok(!success || broken(success) /* Win 2000/XP/8 */, "PeekMessageA succeeded\n");
2917 if (success)
2919 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2920 ok(msg.wParam == 41, "expected msg.wParam = 41, got %lu\n", msg.wParam);
2922 index = WaitForSingleObject(thread, 200);
2923 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2924 CloseHandle(thread);
2926 index = 0xdeadbeef;
2927 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2928 PostMessageA(hWnd, WM_QUIT, 42, 0);
2929 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2930 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2931 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2932 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2933 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2934 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2935 ok(!success, "CoWaitForMultipleHandles didn't pump all WM_DDE_FIRST messages\n");
2936 memset(&msg, 0, sizeof(msg));
2937 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2938 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2939 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2940 ok(msg.wParam == 42, "expected msg.wParam = 42, got %lu\n", msg.wParam);
2941 index = WaitForSingleObject(thread, 200);
2942 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2943 CloseHandle(thread);
2945 PostQuitMessage(43);
2946 memset(&msg, 0, sizeof(msg));
2947 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2948 ok(success || broken(!success) /* Win 8 */, "PeekMessageA failed, error %u\n", GetLastError());
2949 if (!success)
2950 win_skip("PostQuitMessage didn't queue a WM_QUIT message, skipping tests\n");
2951 else
2953 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2954 ok(msg.wParam == 43, "expected msg.wParam = 43, got %lu\n", msg.wParam);
2955 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2956 ok(!success, "PeekMessageA succeeded\n");
2958 index = 0xdeadbeef;
2959 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2960 PostQuitMessage(44);
2961 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2962 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2963 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2964 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2965 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2966 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2967 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2968 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2969 ok(!success, "PeekMessageA succeeded\n");
2970 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2971 ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n");
2972 index = WaitForSingleObject(thread, 200);
2973 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2974 CloseHandle(thread);
2976 index = 0xdeadbeef;
2977 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2978 PostQuitMessage(45);
2979 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2980 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2981 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2982 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2983 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2984 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2985 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2986 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2987 ok(!success, "PeekMessageA succeeded\n");
2988 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2989 ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n");
2990 index = WaitForSingleObject(thread, 200);
2991 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2992 CloseHandle(thread);
2995 /* test message pumping when CoWaitForMultipleHandles is called from non main apartment thread */
2996 thread = CreateThread(NULL, 0, test_CoWaitForMultipleHandles_thread, handles, 0, &tid);
2997 index = WaitForSingleObject(thread, 500);
2998 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2999 CloseHandle(thread);
3001 CoUninitialize();
3003 /* If COM was not initialized, messages are neither pumped nor peeked at */
3004 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3005 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3006 ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr);
3007 success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE);
3008 ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success);
3009 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3010 ok(success, "PeekMessage failed: %u\n", GetLastError());
3012 /* same in an MTA */
3013 CoInitializeEx(NULL, COINIT_MULTITHREADED);
3015 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3016 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3017 ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr);
3018 success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE);
3019 ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success);
3020 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3021 ok(success, "PeekMessage failed: %u\n", GetLastError());
3023 CoUninitialize();
3025 CloseHandle(handles[0]);
3026 CloseHandle(handles[1]);
3027 DestroyWindow(hWnd);
3029 success = UnregisterClassA(cls_name, GetModuleHandleA(0));
3030 ok(success, "UnregisterClass failed %u\n", GetLastError());
3033 static void test_CoGetMalloc(void)
3035 IMalloc *imalloc;
3036 HRESULT hr;
3038 if (0) /* crashes on native */
3039 hr = CoGetMalloc(0, NULL);
3041 imalloc = (void*)0xdeadbeef;
3042 hr = CoGetMalloc(0, &imalloc);
3043 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3044 ok(imalloc == NULL, "got %p\n", imalloc);
3046 imalloc = (void*)0xdeadbeef;
3047 hr = CoGetMalloc(MEMCTX_SHARED, &imalloc);
3048 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3049 ok(imalloc == NULL, "got %p\n", imalloc);
3051 imalloc = (void*)0xdeadbeef;
3052 hr = CoGetMalloc(MEMCTX_MACSYSTEM, &imalloc);
3053 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3054 ok(imalloc == NULL, "got %p\n", imalloc);
3056 imalloc = (void*)0xdeadbeef;
3057 hr = CoGetMalloc(MEMCTX_UNKNOWN, &imalloc);
3058 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3059 ok(imalloc == NULL, "got %p\n", imalloc);
3061 imalloc = (void*)0xdeadbeef;
3062 hr = CoGetMalloc(MEMCTX_SAME, &imalloc);
3063 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3064 ok(imalloc == NULL, "got %p\n", imalloc);
3066 imalloc = NULL;
3067 hr = CoGetMalloc(MEMCTX_TASK, &imalloc);
3068 ok(hr == S_OK, "got 0x%08x\n", hr);
3069 ok(imalloc != NULL, "got %p\n", imalloc);
3070 IMalloc_Release(imalloc);
3073 static void test_CoGetApartmentType(void)
3075 APTTYPEQUALIFIER qualifier;
3076 APTTYPE type;
3077 HRESULT hr;
3079 if (!pCoGetApartmentType)
3081 win_skip("CoGetApartmentType not present\n");
3082 return;
3085 hr = pCoGetApartmentType(NULL, NULL);
3086 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3088 type = 0xdeadbeef;
3089 hr = pCoGetApartmentType(&type, NULL);
3090 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3091 ok(type == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", type);
3093 qualifier = 0xdeadbeef;
3094 hr = pCoGetApartmentType(NULL, &qualifier);
3095 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3096 ok(qualifier == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", qualifier);
3098 type = 0xdeadbeef;
3099 qualifier = 0xdeadbeef;
3100 hr = pCoGetApartmentType(&type, &qualifier);
3101 ok(hr == CO_E_NOTINITIALIZED, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3102 ok(type == APTTYPE_CURRENT, "Expected APTTYPE_CURRENT, got %u\n", type);
3103 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3105 type = 0xdeadbeef;
3106 qualifier = 0xdeadbeef;
3107 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3108 ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr);
3109 hr = pCoGetApartmentType(&type, &qualifier);
3110 ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr);
3111 ok(type == APTTYPE_MAINSTA, "Expected APTTYPE_MAINSTA, got %u\n", type);
3112 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3113 CoUninitialize();
3115 type = 0xdeadbeef;
3116 qualifier = 0xdeadbeef;
3117 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
3118 ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr);
3119 hr = pCoGetApartmentType(&type, &qualifier);
3120 ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr);
3121 ok(type == APTTYPE_MTA, "Expected APTTYPE_MTA, got %u\n", type);
3122 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3123 CoUninitialize();
3126 static HRESULT WINAPI testspy_QI(IMallocSpy *iface, REFIID riid, void **obj)
3128 if (IsEqualIID(riid, &IID_IMallocSpy) || IsEqualIID(riid, &IID_IUnknown))
3130 *obj = iface;
3131 IMallocSpy_AddRef(iface);
3132 return S_OK;
3135 return E_NOINTERFACE;
3138 static ULONG WINAPI testspy_AddRef(IMallocSpy *iface)
3140 return 2;
3143 static ULONG WINAPI testspy_Release(IMallocSpy *iface)
3145 return 1;
3148 static SIZE_T WINAPI testspy_PreAlloc(IMallocSpy *iface, SIZE_T cb)
3150 ok(0, "unexpected call\n");
3151 return 0;
3154 static void* WINAPI testspy_PostAlloc(IMallocSpy *iface, void *ptr)
3156 ok(0, "unexpected call\n");
3157 return NULL;
3160 static void* WINAPI testspy_PreFree(IMallocSpy *iface, void *ptr, BOOL spyed)
3162 ok(0, "unexpected call\n");
3163 return NULL;
3166 static void WINAPI testspy_PostFree(IMallocSpy *iface, BOOL spyed)
3168 ok(0, "unexpected call\n");
3171 static SIZE_T WINAPI testspy_PreRealloc(IMallocSpy *iface, void *ptr, SIZE_T cb, void **newptr, BOOL spyed)
3173 ok(0, "unexpected call\n");
3174 return 0;
3177 static void* WINAPI testspy_PostRealloc(IMallocSpy *iface, void *ptr, BOOL spyed)
3179 ok(0, "unexpected call\n");
3180 return NULL;
3183 static void* WINAPI testspy_PreGetSize(IMallocSpy *iface, void *ptr, BOOL spyed)
3185 ok(0, "unexpected call\n");
3186 return NULL;
3189 static SIZE_T WINAPI testspy_PostGetSize(IMallocSpy *iface, SIZE_T actual, BOOL spyed)
3191 ok(0, "unexpected call\n");
3192 return 0;
3195 static void* WINAPI testspy_PreDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed)
3197 ok(0, "unexpected call\n");
3198 return NULL;
3201 static int WINAPI testspy_PostDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed, int actual)
3203 ok(0, "unexpected call\n");
3204 return 0;
3207 static void WINAPI testspy_PreHeapMinimize(IMallocSpy *iface)
3209 ok(0, "unexpected call\n");
3212 static void WINAPI testspy_PostHeapMinimize(IMallocSpy *iface)
3214 ok(0, "unexpected call\n");
3217 static const IMallocSpyVtbl testspyvtbl =
3219 testspy_QI,
3220 testspy_AddRef,
3221 testspy_Release,
3222 testspy_PreAlloc,
3223 testspy_PostAlloc,
3224 testspy_PreFree,
3225 testspy_PostFree,
3226 testspy_PreRealloc,
3227 testspy_PostRealloc,
3228 testspy_PreGetSize,
3229 testspy_PostGetSize,
3230 testspy_PreDidAlloc,
3231 testspy_PostDidAlloc,
3232 testspy_PreHeapMinimize,
3233 testspy_PostHeapMinimize
3236 static IMallocSpy testspy = { &testspyvtbl };
3238 static void test_IMallocSpy(void)
3240 IMalloc *imalloc;
3241 HRESULT hr;
3243 hr = CoRegisterMallocSpy(NULL);
3244 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3246 hr = CoRevokeMallocSpy();
3247 ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr);
3249 hr = CoRegisterMallocSpy(&testspy);
3250 ok(hr == S_OK, "got 0x%08x\n", hr);
3252 hr = CoRegisterMallocSpy(NULL);
3253 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3255 hr = CoRegisterMallocSpy(&testspy);
3256 ok(hr == CO_E_OBJISREG, "got 0x%08x\n", hr);
3258 imalloc = NULL;
3259 hr = CoGetMalloc(MEMCTX_TASK, &imalloc);
3260 ok(hr == S_OK, "got 0x%08x\n", hr);
3261 ok(imalloc != NULL, "got %p\n", imalloc);
3263 IMalloc_Free(imalloc, NULL);
3265 IMalloc_Release(imalloc);
3267 hr = CoRevokeMallocSpy();
3268 ok(hr == S_OK, "got 0x%08x\n", hr);
3270 hr = CoRevokeMallocSpy();
3271 ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr);
3274 static void test_CoGetCurrentLogicalThreadId(void)
3276 HRESULT hr;
3277 GUID id;
3279 hr = CoGetCurrentLogicalThreadId(NULL);
3280 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3282 id = GUID_NULL;
3283 hr = CoGetCurrentLogicalThreadId(&id);
3284 ok(hr == S_OK, "got 0x%08x\n", hr);
3285 ok(!IsEqualGUID(&id, &GUID_NULL), "got null id\n");
3288 static HRESULT WINAPI testinitialize_QI(IInitializeSpy *iface, REFIID riid, void **obj)
3290 if (IsEqualIID(riid, &IID_IInitializeSpy) || IsEqualIID(riid, &IID_IUnknown))
3292 *obj = iface;
3293 IInitializeSpy_AddRef(iface);
3294 return S_OK;
3297 *obj = NULL;
3298 return E_NOINTERFACE;
3301 static ULONG WINAPI testinitialize_AddRef(IInitializeSpy *iface)
3303 return 2;
3306 static ULONG WINAPI testinitialize_Release(IInitializeSpy *iface)
3308 return 1;
3311 static HRESULT WINAPI testinitialize_PreInitialize(IInitializeSpy *iface, DWORD coinit, DWORD aptrefs)
3313 ok(0, "unexpected call\n");
3314 return E_NOTIMPL;
3317 static HRESULT WINAPI testinitialize_PostInitialize(IInitializeSpy *iface, HRESULT hr, DWORD coinit, DWORD aptrefs)
3319 ok(0, "unexpected call\n");
3320 return E_NOTIMPL;
3323 static HRESULT WINAPI testinitialize_PreUninitialize(IInitializeSpy *iface, DWORD aptrefs)
3325 ok(0, "unexpected call\n");
3326 return E_NOTIMPL;
3329 static HRESULT WINAPI testinitialize_PostUninitialize(IInitializeSpy *iface, DWORD aptrefs)
3331 ok(0, "unexpected call\n");
3332 return E_NOTIMPL;
3335 static const IInitializeSpyVtbl testinitializevtbl =
3337 testinitialize_QI,
3338 testinitialize_AddRef,
3339 testinitialize_Release,
3340 testinitialize_PreInitialize,
3341 testinitialize_PostInitialize,
3342 testinitialize_PreUninitialize,
3343 testinitialize_PostUninitialize
3346 static IInitializeSpy testinitialize = { &testinitializevtbl };
3348 static void test_IInitializeSpy(void)
3350 ULARGE_INTEGER cookie, cookie1, cookie2;
3351 HRESULT hr;
3353 hr = CoRegisterInitializeSpy(NULL, NULL);
3354 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3356 cookie.QuadPart = 1;
3357 hr = CoRegisterInitializeSpy(NULL, &cookie);
3358 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3359 ok(cookie.QuadPart == 1, "got wrong cookie\n");
3361 hr = CoRegisterInitializeSpy(&testinitialize, NULL);
3362 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3364 cookie.HighPart = 0;
3365 cookie.LowPart = 1;
3366 hr = CoRegisterInitializeSpy(&testinitialize, &cookie);
3367 ok(hr == S_OK, "got 0x%08x\n", hr);
3368 todo_wine {
3369 ok(cookie.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie.HighPart,
3370 GetCurrentThreadId());
3371 ok(cookie.LowPart == 0, "got wrong low part 0x%x\n", cookie.LowPart);
3373 /* register same instance one more time */
3374 cookie1.HighPart = 0;
3375 cookie1.LowPart = 0;
3376 hr = CoRegisterInitializeSpy(&testinitialize, &cookie1);
3377 todo_wine {
3378 ok(hr == S_OK, "got 0x%08x\n", hr);
3379 ok(cookie1.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie1.HighPart,
3380 GetCurrentThreadId());
3381 ok(cookie1.LowPart == 1, "got wrong low part 0x%x\n", cookie1.LowPart);
3383 cookie2.HighPart = 0;
3384 cookie2.LowPart = 0;
3385 hr = CoRegisterInitializeSpy(&testinitialize, &cookie2);
3386 todo_wine {
3387 ok(hr == S_OK, "got 0x%08x\n", hr);
3388 ok(cookie2.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie2.HighPart,
3389 GetCurrentThreadId());
3390 ok(cookie2.LowPart == 2, "got wrong low part 0x%x\n", cookie2.LowPart);
3392 hr = CoRevokeInitializeSpy(cookie1);
3393 todo_wine
3394 ok(hr == S_OK, "got 0x%08x\n", hr);
3396 hr = CoRevokeInitializeSpy(cookie1);
3397 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3399 cookie1.HighPart = 0;
3400 cookie1.LowPart = 0;
3401 hr = CoRegisterInitializeSpy(&testinitialize, &cookie1);
3402 todo_wine {
3403 ok(hr == S_OK, "got 0x%08x\n", hr);
3404 ok(cookie1.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie1.HighPart,
3405 GetCurrentThreadId());
3406 ok(cookie1.LowPart == 1, "got wrong low part 0x%x\n", cookie1.LowPart);
3408 hr = CoRevokeInitializeSpy(cookie);
3409 ok(hr == S_OK, "got 0x%08x\n", hr);
3411 hr = CoRevokeInitializeSpy(cookie1);
3412 todo_wine
3413 ok(hr == S_OK, "got 0x%08x\n", hr);
3415 hr = CoRevokeInitializeSpy(cookie2);
3416 todo_wine
3417 ok(hr == S_OK, "got 0x%08x\n", hr);
3420 static HRESULT g_persistfile_qi_ret;
3421 static HRESULT g_persistfile_load_ret;
3422 static HRESULT WINAPI testinstance_QI(IPersistFile *iface, REFIID riid, void **obj)
3424 if (IsEqualIID(riid, &IID_IUnknown)) {
3425 *obj = iface;
3426 IUnknown_AddRef(iface);
3427 return S_OK;
3430 if (IsEqualIID(riid, &IID_IPersistFile)) {
3431 if (SUCCEEDED(g_persistfile_qi_ret)) {
3432 *obj = iface;
3433 IUnknown_AddRef(iface);
3435 else
3436 *obj = NULL;
3437 return g_persistfile_qi_ret;
3440 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
3441 *obj = NULL;
3442 return E_NOINTERFACE;
3445 static ULONG WINAPI testinstance_AddRef(IPersistFile *iface)
3447 return 2;
3450 static ULONG WINAPI testinstance_Release(IPersistFile *iface)
3452 return 1;
3455 static HRESULT WINAPI testinstance_GetClassID(IPersistFile *iface, CLSID *clsid)
3457 ok(0, "unexpected call\n");
3458 return E_NOTIMPL;
3461 static HRESULT WINAPI testinstance_IsDirty(IPersistFile *iface)
3463 ok(0, "unexpected call\n");
3464 return E_NOTIMPL;
3467 static HRESULT WINAPI testinstance_Load(IPersistFile *iface, LPCOLESTR filename, DWORD mode)
3469 return g_persistfile_load_ret;
3472 static HRESULT WINAPI testinstance_Save(IPersistFile *iface, LPCOLESTR filename, BOOL remember)
3474 return E_NOTIMPL;
3477 static HRESULT WINAPI testinstance_SaveCompleted(IPersistFile *iface, LPCOLESTR filename)
3479 ok(0, "unexpected call\n");
3480 return E_NOTIMPL;
3483 static HRESULT WINAPI testinstance_GetCurFile(IPersistFile *iface, LPOLESTR *filename)
3485 ok(0, "unexpected call\n");
3486 return E_NOTIMPL;
3489 static const IPersistFileVtbl testpersistfilevtbl = {
3490 testinstance_QI,
3491 testinstance_AddRef,
3492 testinstance_Release,
3493 testinstance_GetClassID,
3494 testinstance_IsDirty,
3495 testinstance_Load,
3496 testinstance_Save,
3497 testinstance_SaveCompleted,
3498 testinstance_GetCurFile
3501 static IPersistFile testpersistfile = { &testpersistfilevtbl };
3503 static HRESULT WINAPI getinstance_cf_QI(IClassFactory *iface, REFIID riid, void **obj)
3505 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) {
3506 *obj = iface;
3507 IClassFactory_AddRef(iface);
3508 return S_OK;
3511 *obj = NULL;
3512 return E_NOINTERFACE;
3515 static ULONG WINAPI getinstance_cf_AddRef(IClassFactory *iface)
3517 return 2;
3520 static ULONG WINAPI getinstance_cf_Release(IClassFactory *iface)
3522 return 1;
3525 static HRESULT WINAPI getinstance_cf_CreateInstance(IClassFactory *iface, IUnknown *outer,
3526 REFIID riid, void **obj)
3528 if (IsEqualIID(riid, &IID_IUnknown)) {
3529 *obj = &testpersistfile;
3530 return S_OK;
3533 ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid));
3534 *obj = NULL;
3535 return E_NOTIMPL;
3538 static HRESULT WINAPI getinstance_cf_LockServer(IClassFactory *iface, BOOL lock)
3540 ok(0, "unexpected call\n");
3541 return E_NOTIMPL;
3544 static const IClassFactoryVtbl getinstance_cf_vtbl = {
3545 getinstance_cf_QI,
3546 getinstance_cf_AddRef,
3547 getinstance_cf_Release,
3548 getinstance_cf_CreateInstance,
3549 getinstance_cf_LockServer
3552 static IClassFactory getinstance_cf = { &getinstance_cf_vtbl };
3554 static void test_CoGetInstanceFromFile(void)
3556 static const WCHAR filenameW[] = {'d','u','m','m','y','p','a','t','h',0};
3557 CLSID *clsid = (CLSID*)&CLSID_testclsid;
3558 MULTI_QI mqi[2];
3559 DWORD cookie;
3560 HRESULT hr;
3562 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3563 ok(hr == S_OK, "got 0x%08x\n", hr);
3565 /* CLSID is not specified, file does not exist */
3566 mqi[0].pIID = &IID_IUnknown;
3567 mqi[0].pItf = NULL;
3568 mqi[0].hr = E_NOTIMPL;
3569 hr = CoGetInstanceFromFile(NULL, NULL, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3570 todo_wine
3571 ok(hr == MK_E_CANTOPENFILE, "got 0x%08x\n", hr);
3572 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3573 ok(mqi[0].hr == E_NOINTERFACE, "got 0x%08x\n", mqi[0].hr);
3575 /* class is not available */
3576 mqi[0].pIID = &IID_IUnknown;
3577 mqi[0].pItf = NULL;
3578 mqi[0].hr = E_NOTIMPL;
3579 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3580 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
3581 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3582 ok(mqi[0].hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", mqi[0].hr);
3584 hr = CoRegisterClassObject(clsid, (IUnknown*)&getinstance_cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE,
3585 &cookie);
3586 ok(hr == S_OK, "got 0x%08x\n", hr);
3588 mqi[0].pIID = &IID_IUnknown;
3589 mqi[0].pItf = (void*)0xdeadbeef;
3590 mqi[0].hr = S_OK;
3591 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3592 todo_wine {
3593 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3594 ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf);
3596 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3598 mqi[0].pIID = &IID_IUnknown;
3599 mqi[0].pItf = (void*)0xdeadbeef;
3600 mqi[0].hr = E_NOTIMPL;
3601 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3602 todo_wine {
3603 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3604 ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf);
3605 ok(mqi[0].hr == E_NOTIMPL, "got 0x%08x\n", mqi[0].hr);
3607 mqi[0].pIID = &IID_IUnknown;
3608 mqi[0].pItf = NULL;
3609 mqi[0].hr = E_NOTIMPL;
3610 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3611 ok(hr == S_OK, "got 0x%08x\n", hr);
3612 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3613 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3615 mqi[0].pIID = &IID_IUnknown;
3616 mqi[0].pItf = NULL;
3617 mqi[0].hr = S_OK;
3618 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3619 ok(hr == S_OK, "got 0x%08x\n", hr);
3620 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3621 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3623 mqi[0].pIID = &IID_IUnknown;
3624 mqi[0].pItf = NULL;
3625 mqi[0].hr = S_OK;
3626 g_persistfile_qi_ret = S_FALSE;
3627 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3628 ok(hr == S_OK, "got 0x%08x\n", hr);
3629 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3630 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3631 g_persistfile_qi_ret = S_OK;
3633 mqi[0].pIID = &IID_IUnknown;
3634 mqi[0].pItf = NULL;
3635 mqi[0].hr = S_OK;
3636 mqi[1].pIID = &IID_IUnknown;
3637 mqi[1].pItf = NULL;
3638 mqi[1].hr = S_OK;
3639 g_persistfile_qi_ret = 0x8000efef;
3640 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi);
3641 ok(hr == 0x8000efef, "got 0x%08x\n", hr);
3642 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3643 ok(mqi[0].hr == 0x8000efef, "got 0x%08x\n", mqi[0].hr);
3644 ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf);
3645 ok(mqi[1].hr == 0x8000efef, "got 0x%08x\n", mqi[1].hr);
3646 g_persistfile_qi_ret = S_OK;
3648 mqi[0].pIID = &IID_IUnknown;
3649 mqi[0].pItf = NULL;
3650 mqi[0].hr = S_OK;
3651 mqi[1].pIID = &IID_IUnknown;
3652 mqi[1].pItf = NULL;
3653 mqi[1].hr = S_OK;
3654 g_persistfile_load_ret = 0x8000fefe;
3655 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi);
3656 ok(hr == 0x8000fefe, "got 0x%08x\n", hr);
3657 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3658 ok(mqi[0].hr == 0x8000fefe, "got 0x%08x\n", mqi[0].hr);
3659 ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf);
3660 ok(mqi[1].hr == 0x8000fefe, "got 0x%08x\n", mqi[1].hr);
3661 g_persistfile_load_ret = S_OK;
3663 hr = CoRevokeClassObject(cookie);
3664 ok(hr == S_OK, "got 0x%08x\n", hr);
3666 CoUninitialize();
3669 static void test_GlobalOptions(void)
3671 IGlobalOptions *global_options;
3672 HRESULT hres;
3674 CoInitialize(NULL);
3676 hres = CoCreateInstance(&CLSID_GlobalOptions, NULL, CLSCTX_INPROC_SERVER,
3677 &IID_IGlobalOptions, (void**)&global_options);
3678 ok(hres == S_OK || broken(hres == E_NOINTERFACE), "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres);
3679 if(FAILED(hres))
3681 win_skip("CLSID_GlobalOptions not available\n");
3682 CoUninitialize();
3683 return;
3686 IGlobalOptions_Release(global_options);
3688 hres = CoCreateInstance(&CLSID_GlobalOptions, (IUnknown*)0xdeadbeef, CLSCTX_INPROC_SERVER,
3689 &IID_IGlobalOptions, (void**)&global_options);
3690 ok(hres == E_INVALIDARG, "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres);
3692 CoUninitialize();
3695 static void init_funcs(void)
3697 HMODULE hOle32 = GetModuleHandleA("ole32");
3698 HMODULE hAdvapi32 = GetModuleHandleA("advapi32");
3699 HMODULE hkernel32 = GetModuleHandleA("kernel32");
3701 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
3702 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
3703 pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
3704 pCoTreatAsClass = (void*)GetProcAddress(hOle32,"CoTreatAsClass");
3705 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
3706 pCoGetApartmentType = (void*)GetProcAddress(hOle32, "CoGetApartmentType");
3707 pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA");
3708 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
3709 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
3711 pActivateActCtx = (void*)GetProcAddress(hkernel32, "ActivateActCtx");
3712 pCreateActCtxW = (void*)GetProcAddress(hkernel32, "CreateActCtxW");
3713 pDeactivateActCtx = (void*)GetProcAddress(hkernel32, "DeactivateActCtx");
3714 pIsWow64Process = (void*)GetProcAddress(hkernel32, "IsWow64Process");
3715 pReleaseActCtx = (void*)GetProcAddress(hkernel32, "ReleaseActCtx");
3718 static DWORD CALLBACK implicit_mta_proc(void *param)
3720 IComThreadingInfo *threading_info;
3721 ULONG_PTR token;
3722 IUnknown *unk;
3723 DWORD cookie;
3724 CLSID clsid;
3725 HRESULT hr;
3727 test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA);
3729 hr = CoCreateInstance(&CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
3730 ok_ole_success(hr, "CoCreateInstance");
3731 IUnknown_Release(unk);
3733 hr = CoGetClassObject(&CLSID_InternetZoneManager, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&unk);
3734 ok_ole_success(hr, "CoGetClassObject");
3735 IUnknown_Release(unk);
3737 hr = CoGetObjectContext(&IID_IComThreadingInfo, (void **)&threading_info);
3738 ok_ole_success(hr, "CoGetObjectContext");
3739 IComThreadingInfo_Release(threading_info);
3741 hr = CoGetContextToken(&token);
3742 ok_ole_success(hr, "CoGetContextToken");
3744 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
3745 ok_ole_success(hr, "CoRegisterPSClsid");
3747 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
3748 ok_ole_success(hr, "CoGetPSClsid");
3750 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
3751 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
3752 ok_ole_success(hr, "CoRegisterClassObject");
3754 hr = CoRevokeClassObject(cookie);
3755 ok_ole_success(hr, "CoRevokeClassObject");
3757 hr = CoRegisterMessageFilter(NULL, NULL);
3758 ok(hr == CO_E_NOT_SUPPORTED, "got %#x\n", hr);
3760 hr = CoLockObjectExternal((IUnknown *)&Test_Unknown, TRUE, TRUE);
3761 ok_ole_success(hr, "CoLockObjectExternal");
3763 hr = CoDisconnectObject((IUnknown *)&Test_Unknown, 0);
3764 ok_ole_success(hr, "CoDisconnectObject");
3766 return 0;
3769 /* Some COM functions (perhaps even all of them?) can make use of an "implicit"
3770 * multi-threaded apartment created by another thread in the same process. */
3771 static void test_implicit_mta(void)
3773 HANDLE thread;
3775 CoInitializeEx(NULL, COINIT_MULTITHREADED);
3777 thread = CreateThread(NULL, 0, implicit_mta_proc, NULL, 0, NULL);
3778 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
3780 CoUninitialize();
3783 START_TEST(compobj)
3785 init_funcs();
3787 if (!pCoInitializeEx)
3789 trace("You need DCOM95 installed to run this test\n");
3790 return;
3793 if (!pCreateActCtxW)
3794 win_skip("Activation contexts are not supported, some tests will be skipped.\n");
3796 test_ProgIDFromCLSID();
3797 test_CLSIDFromProgID();
3798 test_CLSIDFromString();
3799 test_IIDFromString();
3800 test_StringFromGUID2();
3801 test_CoCreateInstance();
3802 test_ole_menu();
3803 test_CoGetClassObject();
3804 test_CoCreateInstanceEx();
3805 test_CoRegisterMessageFilter();
3806 test_CoRegisterPSClsid();
3807 test_CoGetPSClsid();
3808 test_CoUnmarshalInterface();
3809 test_CoGetInterfaceAndReleaseStream();
3810 test_CoMarshalInterface();
3811 test_CoMarshalInterThreadInterfaceInStream();
3812 test_CoRegisterClassObject();
3813 test_registered_object_thread_affinity();
3814 test_CoFreeUnusedLibraries();
3815 test_CoGetObjectContext();
3816 test_CoGetCallContext();
3817 test_CoGetContextToken();
3818 test_TreatAsClass();
3819 test_CoInitializeEx();
3820 test_OleInitialize_InitCounting();
3821 test_OleRegGetMiscStatus();
3822 test_CoCreateGuid();
3823 test_CoWaitForMultipleHandles();
3824 test_CoGetMalloc();
3825 test_OleRegGetUserType();
3826 test_CoGetApartmentType();
3827 test_IMallocSpy();
3828 test_CoGetCurrentLogicalThreadId();
3829 test_IInitializeSpy();
3830 test_CoGetInstanceFromFile();
3831 test_GlobalOptions();
3832 test_implicit_mta();