cc230eee3443e20f7ab92503a73d6c2c3dbff1ea
[reactos.git] / rostests / winetests / ole32 / compobj.c
1 /*
2 * Component Object Tests
3 *
4 * Copyright 2005 Robert Shearman
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27
28 #include <stdarg.h>
29 #include <stdio.h>
30
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <winreg.h>
35 #define USE_COM_CONTEXT_DEF
36 #include <initguid.h>
37 //#include "objbase.h"
38 //#include "shlguid.h"
39 #include <ole2.h>
40 #include <urlmon.h> /* for CLSID_FileProtocol */
41 #include <dde.h>
42
43 #include <ctxtcall.h>
44
45 #include <wine/test.h>
46
47 extern const IID GUID_NULL;
48
49 #define DEFINE_EXPECT(func) \
50 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
51
52 #define SET_EXPECT(func) \
53 expect_ ## func = TRUE
54
55 #define CHECK_EXPECT2(func) \
56 do { \
57 ok(expect_ ##func, "unexpected call " #func "\n"); \
58 called_ ## func = TRUE; \
59 }while(0)
60
61 #define CHECK_EXPECT(func) \
62 do { \
63 CHECK_EXPECT2(func); \
64 expect_ ## func = FALSE; \
65 }while(0)
66
67 #define CHECK_CALLED(func) \
68 do { \
69 ok(called_ ## func, "expected " #func "\n"); \
70 expect_ ## func = called_ ## func = FALSE; \
71 }while(0)
72
73 DEFINE_EXPECT(CreateStub);
74
75 /* functions that are not present on all versions of Windows */
76 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
77 static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
78 static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
79 static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
80 static HRESULT (WINAPI * pCoTreatAsClass)(REFCLSID clsidOld, REFCLSID pClsidNew);
81 static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
82 static HRESULT (WINAPI * pCoGetApartmentType)(APTTYPE *type, APTTYPEQUALIFIER *qualifier);
83 static LONG (WINAPI * pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
84 static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
85
86 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
87 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
88 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
89 static BOOL (WINAPI *pIsWow64Process)(HANDLE, LPBOOL);
90 static void (WINAPI *pReleaseActCtx)(HANDLE);
91
92 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
93 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
94 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
95
96 static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
97 static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
98 static const GUID IID_Testiface = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
99 static const GUID IID_Testiface2 = { 0x32222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
100 static const GUID IID_Testiface3 = { 0x42222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
101 static const GUID IID_Testiface4 = { 0x52222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
102 static const GUID IID_Testiface5 = { 0x62222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
103 static const GUID IID_Testiface6 = { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
104 static const GUID IID_TestPS = { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } };
105
106 DEFINE_GUID(CLSID_InProcFreeMarshaler, 0x0000033a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
107 DEFINE_GUID(CLSID_testclsid, 0xacd014c7,0x9535,0x4fac,0x8b,0x53,0xa4,0x8c,0xa7,0xf4,0xd7,0x26);
108
109 static const WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
110 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
111 static const WCHAR wszCLSID_StdFont[] =
112 {
113 '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
114 '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
115 };
116 static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
117 static const WCHAR cf_brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
118 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0};
119
120 DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
121 DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
122
123 static LONG cLocks;
124
125 static void LockModule(void)
126 {
127 InterlockedIncrement(&cLocks);
128 }
129
130 static void UnlockModule(void)
131 {
132 InterlockedDecrement(&cLocks);
133 }
134
135 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
136 LPCLASSFACTORY iface,
137 REFIID riid,
138 LPVOID *ppvObj)
139 {
140 if (ppvObj == NULL) return E_POINTER;
141
142 if (IsEqualGUID(riid, &IID_IUnknown) ||
143 IsEqualGUID(riid, &IID_IClassFactory))
144 {
145 *ppvObj = iface;
146 IClassFactory_AddRef(iface);
147 return S_OK;
148 }
149
150 *ppvObj = NULL;
151 return E_NOINTERFACE;
152 }
153
154 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
155 {
156 LockModule();
157 return 2; /* non-heap-based object */
158 }
159
160 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
161 {
162 UnlockModule();
163 return 1; /* non-heap-based object */
164 }
165
166 static IID create_instance_iid;
167 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
168 LPCLASSFACTORY iface,
169 IUnknown *pUnkOuter,
170 REFIID riid,
171 LPVOID *ppvObj)
172 {
173 *ppvObj = NULL;
174 create_instance_iid = *riid;
175 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
176 return E_NOINTERFACE;
177 }
178
179 static HRESULT WINAPI Test_IClassFactory_LockServer(
180 LPCLASSFACTORY iface,
181 BOOL fLock)
182 {
183 return S_OK;
184 }
185
186 static const IClassFactoryVtbl TestClassFactory_Vtbl =
187 {
188 Test_IClassFactory_QueryInterface,
189 Test_IClassFactory_AddRef,
190 Test_IClassFactory_Release,
191 Test_IClassFactory_CreateInstance,
192 Test_IClassFactory_LockServer
193 };
194
195 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
196
197 static WCHAR manifest_path[MAX_PATH];
198
199 static BOOL create_manifest_file(const char *filename, const char *manifest)
200 {
201 int manifest_len;
202 DWORD size;
203 HANDLE file;
204 WCHAR path[MAX_PATH];
205
206 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
207 GetFullPathNameW(path, sizeof(manifest_path)/sizeof(WCHAR), manifest_path, NULL);
208
209 manifest_len = strlen(manifest);
210 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
211 FILE_ATTRIBUTE_NORMAL, NULL);
212 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
213 if(file == INVALID_HANDLE_VALUE)
214 return FALSE;
215 WriteFile(file, manifest, manifest_len, &size, NULL);
216 CloseHandle(file);
217
218 return TRUE;
219 }
220
221 static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie)
222 {
223 WCHAR path[MAX_PATH];
224 ACTCTXW actctx;
225 HANDLE handle;
226 BOOL ret;
227
228 if (!pCreateActCtxW) return NULL;
229
230 create_manifest_file("file.manifest", manifest);
231
232 MultiByteToWideChar( CP_ACP, 0, "file.manifest", -1, path, MAX_PATH );
233 memset(&actctx, 0, sizeof(ACTCTXW));
234 actctx.cbSize = sizeof(ACTCTXW);
235 actctx.lpSource = path;
236
237 handle = pCreateActCtxW(&actctx);
238 ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* some old XP/2k3 versions */,
239 "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
240 if (handle == INVALID_HANDLE_VALUE)
241 {
242 win_skip("activation context generation failed, some tests will be skipped\n");
243 handle = NULL;
244 }
245
246 ok(actctx.cbSize == sizeof(ACTCTXW), "actctx.cbSize=%d\n", actctx.cbSize);
247 ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
248 ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
249 ok(actctx.wProcessorArchitecture == 0, "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
250 ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId);
251 ok(actctx.lpAssemblyDirectory == NULL, "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
252 ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
253 ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n", actctx.lpApplicationName);
254 ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
255
256 DeleteFileA("file.manifest");
257
258 if (handle)
259 {
260 ret = pActivateActCtx(handle, cookie);
261 ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
262 }
263
264 return handle;
265 }
266
267 static const char actctx_manifest[] =
268 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
269 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
270 " publicKeyToken=\"6595b6414666f1df\" />"
271 "<file name=\"testlib.dll\">"
272 " <comClass"
273 " clsid=\"{0000033a-0000-0000-c000-000000000046}\""
274 " progid=\"FTMarshal\""
275 " />"
276 " <comClass"
277 " clsid=\"{5201163f-8164-4fd0-a1a2-5d5a3654d3bd}\""
278 " progid=\"WineOOPTest\""
279 " />"
280 " <comClass description=\"Test com class\""
281 " clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
282 " progid=\"ProgId.ProgId\""
283 " miscStatusIcon=\"recomposeonresize\""
284 " />"
285 " <comClass description=\"CustomFont Description\" clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb851}\""
286 " progid=\"CustomFont\""
287 " miscStatusIcon=\"recomposeonresize\""
288 " miscStatusContent=\"insideout\""
289 " />"
290 " <comClass description=\"StdFont Description\" clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
291 " progid=\"StdFont\""
292 " />"
293 " <comClass clsid=\"{62222222-1234-1234-1234-56789abcdef0}\" >"
294 " <progid>ProgId.ProgId.1</progid>"
295 " </comClass>"
296 " <comInterfaceProxyStub "
297 " name=\"Iifaceps\""
298 " iid=\"{22222222-1234-1234-1234-56789abcdef0}\""
299 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
300 " />"
301 "</file>"
302 " <comInterfaceExternalProxyStub "
303 " name=\"Iifaceps2\""
304 " iid=\"{32222222-1234-1234-1234-56789abcdef0}\""
305 " />"
306 " <comInterfaceExternalProxyStub "
307 " name=\"Iifaceps3\""
308 " iid=\"{42222222-1234-1234-1234-56789abcdef0}\""
309 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
310 " />"
311 " <comInterfaceExternalProxyStub "
312 " name=\"Iifaceps4\""
313 " iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
314 " proxyStubClsid32=\"{00000000-0000-0000-0000-000000000000}\""
315 " />"
316 " <clrClass "
317 " clsid=\"{72222222-1234-1234-1234-56789abcdef0}\""
318 " name=\"clrclass\""
319 " >"
320 " <progid>clrprogid.1</progid>"
321 " </clrClass>"
322 "</assembly>";
323
324 DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
325
326 static void test_ProgIDFromCLSID(void)
327 {
328 ULONG_PTR cookie = 0;
329 LPWSTR progid;
330 HANDLE handle;
331 HRESULT hr;
332
333 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
334 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
335 if (hr == S_OK)
336 {
337 ok(!lstrcmpiW(progid, stdfont), "Didn't get expected prog ID\n");
338 CoTaskMemFree(progid);
339 }
340
341 progid = (LPWSTR)0xdeadbeef;
342 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
343 ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
344 ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
345
346 hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
347 ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
348
349 if ((handle = activate_context(actctx_manifest, &cookie)))
350 {
351 static const WCHAR customfontW[] = {'C','u','s','t','o','m','F','o','n','t',0};
352
353 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
354 ok(hr == S_OK, "got 0x%08x\n", hr);
355 ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid));
356 CoTaskMemFree(progid);
357
358 /* try something registered and redirected */
359 progid = NULL;
360 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
361 ok(hr == S_OK, "got 0x%08x\n", hr);
362 ok(!lstrcmpiW(progid, customfontW), "got wrong progid %s\n", wine_dbgstr_w(progid));
363 CoTaskMemFree(progid);
364
365 /* classes without default progid, progid list is not used */
366 hr = ProgIDFromCLSID(&IID_Testiface5, &progid);
367 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
368
369 hr = ProgIDFromCLSID(&IID_Testiface6, &progid);
370 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
371
372 pDeactivateActCtx(0, cookie);
373 pReleaseActCtx(handle);
374 }
375 }
376
377 static void test_CLSIDFromProgID(void)
378 {
379 ULONG_PTR cookie = 0;
380 HANDLE handle;
381 CLSID clsid;
382 HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
383 ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
384 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
385
386 hr = CLSIDFromString(stdfont, &clsid);
387 ok_ole_success(hr, "CLSIDFromString");
388 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
389
390 /* test some failure cases */
391
392 hr = CLSIDFromProgID(wszNonExistent, NULL);
393 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
394
395 hr = CLSIDFromProgID(NULL, &clsid);
396 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
397
398 memset(&clsid, 0xcc, sizeof(clsid));
399 hr = CLSIDFromProgID(wszNonExistent, &clsid);
400 ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
401 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
402
403 /* fails without proper context */
404 memset(&clsid, 0xcc, sizeof(clsid));
405 hr = CLSIDFromProgID(progidW, &clsid);
406 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
407 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "wrong clsid\n");
408
409 if ((handle = activate_context(actctx_manifest, &cookie)))
410 {
411 GUID clsid1;
412
413 memset(&clsid, 0xcc, sizeof(clsid));
414 hr = CLSIDFromProgID(wszNonExistent, &clsid);
415 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
416 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "should have zero CLSID on failure\n");
417
418 /* CLSIDFromString() doesn't check activation context */
419 hr = CLSIDFromString(progidW, &clsid);
420 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
421
422 clsid = CLSID_NULL;
423 hr = CLSIDFromProgID(progidW, &clsid);
424 ok(hr == S_OK, "got 0x%08x\n", hr);
425 /* it returns generated CLSID here */
426 ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL),
427 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid));
428
429 /* duplicate progid present in context - returns generated guid here too */
430 clsid = CLSID_NULL;
431 hr = CLSIDFromProgID(stdfont, &clsid);
432 ok(hr == S_OK, "got 0x%08x\n", hr);
433 clsid1 = CLSID_StdFont;
434 /* that's where it differs from StdFont */
435 clsid1.Data4[7] = 0x52;
436 ok(!IsEqualCLSID(&clsid, &CLSID_StdFont) && !IsEqualCLSID(&clsid, &CLSID_NULL) && !IsEqualCLSID(&clsid, &clsid1),
437 "got %s\n", wine_dbgstr_guid(&clsid));
438
439 pDeactivateActCtx(0, cookie);
440 pReleaseActCtx(handle);
441 }
442 }
443
444 static void test_CLSIDFromString(void)
445 {
446 CLSID clsid;
447 WCHAR wszCLSID_Broken[50];
448 UINT i;
449
450 HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
451 ok_ole_success(hr, "CLSIDFromString");
452 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
453
454 memset(&clsid, 0xab, sizeof(clsid));
455 hr = CLSIDFromString(NULL, &clsid);
456 ok(hr == S_OK, "got 0x%08x\n", hr);
457 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
458
459 /* string is longer, but starts with a valid CLSID */
460 memset(&clsid, 0, sizeof(clsid));
461 hr = CLSIDFromString(cf_brokenW, &clsid);
462 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
463 ok(IsEqualCLSID(&clsid, &IID_IClassFactory), "got %s\n", wine_dbgstr_guid(&clsid));
464
465 lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
466 for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
467 wszCLSID_Broken[i] = 'A';
468 wszCLSID_Broken[i] = '\0';
469
470 memset(&clsid, 0, sizeof(CLSID));
471 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
472 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
473 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
474
475 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
476 memset(&clsid, 0, sizeof(CLSID));
477 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
478 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
479 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
480
481 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
482 memset(&clsid, 0, sizeof(CLSID));
483 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
484 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
485 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
486
487 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
488 memset(&clsid, 0, sizeof(CLSID));
489 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
490 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
491 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
492
493 memset(&clsid, 0xcc, sizeof(CLSID));
494 hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
495 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
496 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
497
498 wszCLSID_Broken[9] = '*';
499 memset(&clsid, 0xcc, sizeof(CLSID));
500 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
501 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
502 ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
503 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
504
505 wszCLSID_Broken[3] = '*';
506 memset(&clsid, 0xcc, sizeof(CLSID));
507 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
508 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
509 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
510 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
511
512 wszCLSID_Broken[3] = '\0';
513 memset(&clsid, 0xcc, sizeof(CLSID));
514 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
515 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
516 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
517 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
518 }
519
520 static void test_IIDFromString(void)
521 {
522 static const WCHAR cfW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
523 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
524 static const WCHAR brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
525 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
526 static const WCHAR broken2W[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
527 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
528 static const WCHAR broken3W[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
529 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
530 HRESULT hr;
531 IID iid;
532
533 hr = IIDFromString(wszCLSID_StdFont, &iid);
534 ok(hr == S_OK, "got 0x%08x\n", hr);
535 ok(IsEqualIID(&iid, &CLSID_StdFont), "got iid %s\n", wine_dbgstr_guid(&iid));
536
537 memset(&iid, 0xab, sizeof(iid));
538 hr = IIDFromString(NULL, &iid);
539 ok(hr == S_OK, "got 0x%08x\n", hr);
540 ok(IsEqualIID(&iid, &CLSID_NULL), "got iid %s\n", wine_dbgstr_guid(&iid));
541
542 hr = IIDFromString(cfW, &iid);
543 ok(hr == S_OK, "got 0x%08x\n", hr);
544 ok(IsEqualIID(&iid, &IID_IClassFactory), "got iid %s\n", wine_dbgstr_guid(&iid));
545
546 /* string starts with a valid IID but is longer */
547 memset(&iid, 0xab, sizeof(iid));
548 hr = IIDFromString(cf_brokenW, &iid);
549 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
550 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
551
552 /* invalid IID in a valid format */
553 memset(&iid, 0xab, sizeof(iid));
554 hr = IIDFromString(brokenW, &iid);
555 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
556 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
557
558 memset(&iid, 0xab, sizeof(iid));
559 hr = IIDFromString(broken2W, &iid);
560 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
561 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
562
563 /* format is broken, but string length is okay */
564 memset(&iid, 0xab, sizeof(iid));
565 hr = IIDFromString(broken3W, &iid);
566 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
567 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
568
569 /* invalid string */
570 memset(&iid, 0xab, sizeof(iid));
571 hr = IIDFromString(wszNonExistent, &iid);
572 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
573 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
574
575 /* valid ProgID */
576 memset(&iid, 0xab, sizeof(iid));
577 hr = IIDFromString(stdfont, &iid);
578 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
579 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
580 }
581
582 static void test_StringFromGUID2(void)
583 {
584 WCHAR str[50];
585 int len;
586
587 /* invalid pointer */
588 SetLastError(0xdeadbeef);
589 len = StringFromGUID2(NULL,str,50);
590 ok(len == 0, "len: %d (expected 0)\n", len);
591 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
592
593 /* Test corner cases for buffer size */
594 len = StringFromGUID2(&CLSID_StdFont,str,50);
595 ok(len == 39, "len: %d (expected 39)\n", len);
596 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
597
598 memset(str,0,sizeof str);
599 len = StringFromGUID2(&CLSID_StdFont,str,39);
600 ok(len == 39, "len: %d (expected 39)\n", len);
601 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
602
603 len = StringFromGUID2(&CLSID_StdFont,str,38);
604 ok(len == 0, "len: %d (expected 0)\n", len);
605
606 len = StringFromGUID2(&CLSID_StdFont,str,30);
607 ok(len == 0, "len: %d (expected 0)\n", len);
608 }
609
610 struct info
611 {
612 HANDLE wait, stop;
613 };
614
615 static DWORD CALLBACK ole_initialize_thread(LPVOID pv)
616 {
617 HRESULT hr;
618 struct info *info = pv;
619
620 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
621
622 SetEvent(info->wait);
623 WaitForSingleObject(info->stop, 10000);
624
625 CoUninitialize();
626 return hr;
627 }
628
629 #define test_apt_type(t, q, t_t, t_q) _test_apt_type(t, q, t_t, t_q, __LINE__)
630 static void _test_apt_type(APTTYPE expected_type, APTTYPEQUALIFIER expected_qualifier, BOOL todo_type,
631 BOOL todo_qualifier, int line)
632 {
633 APTTYPEQUALIFIER qualifier = ~0u;
634 APTTYPE type = ~0u;
635 HRESULT hr;
636
637 if (!pCoGetApartmentType)
638 return;
639
640 hr = pCoGetApartmentType(&type, &qualifier);
641 ok_(__FILE__, line)(hr == S_OK || hr == CO_E_NOTINITIALIZED, "Unexpected return code: 0x%08x\n", hr);
642 todo_wine_if(todo_type)
643 ok_(__FILE__, line)(type == expected_type, "Wrong apartment type %d, expected %d\n", type, expected_type);
644 todo_wine_if(todo_qualifier)
645 ok_(__FILE__, line)(qualifier == expected_qualifier, "Wrong apartment qualifier %d, expected %d\n", qualifier,
646 expected_qualifier);
647 }
648
649 static void test_CoCreateInstance(void)
650 {
651 HRESULT hr;
652 HANDLE thread;
653 DWORD tid, exitcode;
654 IUnknown *pUnk;
655 struct info info;
656 REFCLSID rclsid = &CLSID_InternetZoneManager;
657
658 pUnk = (IUnknown *)0xdeadbeef;
659 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
660 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
661 ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
662
663 OleInitialize(NULL);
664
665 /* test errors returned for non-registered clsids */
666 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
667 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
668 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pUnk);
669 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
670 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (void **)&pUnk);
671 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
672 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_REMOTE_SERVER, &IID_IUnknown, (void **)&pUnk);
673 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
674
675 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
676 if(hr == REGDB_E_CLASSNOTREG)
677 {
678 skip("IE not installed so can't test CoCreateInstance\n");
679 OleUninitialize();
680 return;
681 }
682
683 ok_ole_success(hr, "CoCreateInstance");
684 if(pUnk) IUnknown_Release(pUnk);
685 OleUninitialize();
686
687 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
688 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
689
690 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
691 thread has already done so */
692
693 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
694
695 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
696 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
697
698 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
699 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
700
701 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
702 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
703
704 ok( !WaitForSingleObject(info.wait, 10000 ), "wait timed out\n" );
705
706 test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA, TRUE, TRUE);
707
708 pUnk = (IUnknown *)0xdeadbeef;
709 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
710 ok(hr == S_OK, "CoCreateInstance should have returned S_OK instead of 0x%08x\n", hr);
711 if (pUnk) IUnknown_Release(pUnk);
712
713 SetEvent(info.stop);
714 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
715
716 GetExitCodeThread(thread, &exitcode);
717 hr = exitcode;
718 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
719
720 CloseHandle(thread);
721 CloseHandle(info.wait);
722 CloseHandle(info.stop);
723
724 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
725 }
726
727 static void test_CoGetClassObject(void)
728 {
729 HRESULT hr;
730 HANDLE thread, handle;
731 DWORD tid, exitcode;
732 ULONG_PTR cookie;
733 IUnknown *pUnk;
734 struct info info;
735 REFCLSID rclsid = &CLSID_InternetZoneManager;
736 HKEY hkey;
737 LONG res;
738
739 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
740 ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
741 ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
742
743 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
744 ok(hr == E_INVALIDARG ||
745 broken(hr == CO_E_NOTINITIALIZED), /* win9x */
746 "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
747
748 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
749 thread has already done so */
750
751 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
752
753 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
754 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
755
756 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
757 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
758
759 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
760 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
761
762 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
763
764 test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA, TRUE, TRUE);
765
766 pUnk = (IUnknown *)0xdeadbeef;
767 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
768 if(hr == REGDB_E_CLASSNOTREG)
769 skip("IE not installed so can't test CoGetClassObject\n");
770 else
771 {
772 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
773 if (pUnk) IUnknown_Release(pUnk);
774 }
775
776 SetEvent(info.stop);
777 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
778
779 GetExitCodeThread(thread, &exitcode);
780 hr = exitcode;
781 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
782
783 CloseHandle(thread);
784 CloseHandle(info.wait);
785 CloseHandle(info.stop);
786
787 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
788
789 if (!pRegOverridePredefKey)
790 {
791 win_skip("RegOverridePredefKey not available\n");
792 return;
793 }
794
795 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
796
797 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
798 if (hr == S_OK)
799 {
800 IUnknown_Release(pUnk);
801
802 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
803 KEY_ALL_ACCESS, NULL, &hkey, NULL);
804 ok(!res, "RegCreateKeyEx returned %d\n", res);
805
806 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
807 ok(!res, "RegOverridePredefKey returned %d\n", res);
808
809 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
810 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
811
812 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
813 ok(!res, "RegOverridePredefKey returned %d\n", res);
814
815 if (hr == S_OK) IUnknown_Release(pUnk);
816 RegCloseKey(hkey);
817 }
818
819 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
820 ok(hr == S_OK, "got 0x%08x\n", hr);
821 IUnknown_Release(pUnk);
822
823 /* context redefines FreeMarshaler CLSID */
824 if ((handle = activate_context(actctx_manifest, &cookie)))
825 {
826 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
827 ok(hr == S_OK, "got 0x%08x\n", hr);
828 IUnknown_Release(pUnk);
829
830 pDeactivateActCtx(0, cookie);
831 pReleaseActCtx(handle);
832 }
833
834 CoUninitialize();
835 }
836
837 static void test_CoCreateInstanceEx(void)
838 {
839 MULTI_QI qi_res = { &IID_IMoniker };
840 DWORD cookie;
841 HRESULT hr;
842
843 CoInitialize(NULL);
844
845 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
846 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
847 ok_ole_success(hr, "CoRegisterClassObject");
848
849 create_instance_iid = IID_NULL;
850 hr = CoCreateInstanceEx(&CLSID_WineOOPTest, NULL, CLSCTX_INPROC_SERVER, NULL, 1, &qi_res);
851 ok(hr == E_NOINTERFACE, "CoCreateInstanceEx failed: %08x\n", hr);
852 ok(IsEqualGUID(&create_instance_iid, qi_res.pIID), "Unexpected CreateInstance iid %s\n",
853 wine_dbgstr_guid(&create_instance_iid));
854
855 hr = CoRevokeClassObject(cookie);
856 ok_ole_success(hr, "CoRevokeClassObject");
857
858 CoUninitialize();
859 }
860
861 static ATOM register_dummy_class(void)
862 {
863 WNDCLASSA wc =
864 {
865 0,
866 DefWindowProcA,
867 0,
868 0,
869 GetModuleHandleA(NULL),
870 NULL,
871 LoadCursorA(NULL, (LPSTR)IDC_ARROW),
872 (HBRUSH)(COLOR_BTNFACE+1),
873 NULL,
874 "WineOleTestClass",
875 };
876
877 return RegisterClassA(&wc);
878 }
879
880 static void test_ole_menu(void)
881 {
882 HWND hwndFrame;
883 HRESULT hr;
884
885 hwndFrame = CreateWindowA((LPCSTR)MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
886 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
887 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
888
889 DestroyWindow(hwndFrame);
890 }
891
892
893 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
894 {
895 if (ppvObj == NULL) return E_POINTER;
896
897 if (IsEqualGUID(riid, &IID_IUnknown) ||
898 IsEqualGUID(riid, &IID_IClassFactory))
899 {
900 *ppvObj = iface;
901 IMessageFilter_AddRef(iface);
902 return S_OK;
903 }
904
905 return E_NOINTERFACE;
906 }
907
908 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
909 {
910 return 2; /* non-heap object */
911 }
912
913 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
914 {
915 return 1; /* non-heap object */
916 }
917
918 static DWORD WINAPI MessageFilter_HandleInComingCall(
919 IMessageFilter *iface,
920 DWORD dwCallType,
921 HTASK threadIDCaller,
922 DWORD dwTickCount,
923 LPINTERFACEINFO lpInterfaceInfo)
924 {
925 trace("HandleInComingCall\n");
926 return SERVERCALL_ISHANDLED;
927 }
928
929 static DWORD WINAPI MessageFilter_RetryRejectedCall(
930 IMessageFilter *iface,
931 HTASK threadIDCallee,
932 DWORD dwTickCount,
933 DWORD dwRejectType)
934 {
935 trace("RetryRejectedCall\n");
936 return 0;
937 }
938
939 static DWORD WINAPI MessageFilter_MessagePending(
940 IMessageFilter *iface,
941 HTASK threadIDCallee,
942 DWORD dwTickCount,
943 DWORD dwPendingType)
944 {
945 trace("MessagePending\n");
946 return PENDINGMSG_WAITNOPROCESS;
947 }
948
949 static const IMessageFilterVtbl MessageFilter_Vtbl =
950 {
951 MessageFilter_QueryInterface,
952 MessageFilter_AddRef,
953 MessageFilter_Release,
954 MessageFilter_HandleInComingCall,
955 MessageFilter_RetryRejectedCall,
956 MessageFilter_MessagePending
957 };
958
959 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
960
961 static void test_CoRegisterMessageFilter(void)
962 {
963 HRESULT hr;
964 IMessageFilter *prev_filter;
965
966 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
967 ok(hr == CO_E_NOT_SUPPORTED,
968 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
969 hr);
970
971 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
972 prev_filter = (IMessageFilter *)0xdeadbeef;
973 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
974 ok(hr == CO_E_NOT_SUPPORTED,
975 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
976 hr);
977 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
978 "prev_filter should have been set to %p\n", prev_filter);
979 CoUninitialize();
980
981 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
982
983 hr = CoRegisterMessageFilter(NULL, NULL);
984 ok_ole_success(hr, "CoRegisterMessageFilter");
985
986 prev_filter = (IMessageFilter *)0xdeadbeef;
987 hr = CoRegisterMessageFilter(NULL, &prev_filter);
988 ok_ole_success(hr, "CoRegisterMessageFilter");
989 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
990
991 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
992 ok_ole_success(hr, "CoRegisterMessageFilter");
993 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
994
995 hr = CoRegisterMessageFilter(NULL, NULL);
996 ok_ole_success(hr, "CoRegisterMessageFilter");
997
998 CoUninitialize();
999 }
1000
1001 static IUnknown Test_Unknown;
1002
1003 static HRESULT WINAPI EnumOLEVERB_QueryInterface(IEnumOLEVERB *iface, REFIID riid, void **ppv)
1004 {
1005 return IUnknown_QueryInterface(&Test_Unknown, riid, ppv);
1006 }
1007
1008 static ULONG WINAPI EnumOLEVERB_AddRef(IEnumOLEVERB *iface)
1009 {
1010 return 2;
1011 }
1012
1013 static ULONG WINAPI EnumOLEVERB_Release(IEnumOLEVERB *iface)
1014 {
1015 return 1;
1016 }
1017
1018 static HRESULT WINAPI EnumOLEVERB_Next(IEnumOLEVERB *iface, ULONG celt, OLEVERB *rgelt, ULONG *fetched)
1019 {
1020 ok(0, "unexpected call\n");
1021 return E_NOTIMPL;
1022 }
1023
1024 static HRESULT WINAPI EnumOLEVERB_Skip(IEnumOLEVERB *iface, ULONG celt)
1025 {
1026 ok(0, "unexpected call\n");
1027 return E_NOTIMPL;
1028 }
1029
1030 static HRESULT WINAPI EnumOLEVERB_Reset(IEnumOLEVERB *iface)
1031 {
1032 ok(0, "unexpected call\n");
1033 return E_NOTIMPL;
1034 }
1035
1036 static HRESULT WINAPI EnumOLEVERB_Clone(IEnumOLEVERB *iface, IEnumOLEVERB **ppenum)
1037 {
1038 ok(0, "unexpected call\n");
1039 return E_NOTIMPL;
1040 }
1041
1042 static const IEnumOLEVERBVtbl EnumOLEVERBVtbl = {
1043 EnumOLEVERB_QueryInterface,
1044 EnumOLEVERB_AddRef,
1045 EnumOLEVERB_Release,
1046 EnumOLEVERB_Next,
1047 EnumOLEVERB_Skip,
1048 EnumOLEVERB_Reset,
1049 EnumOLEVERB_Clone
1050 };
1051
1052 static IEnumOLEVERB EnumOLEVERB = { &EnumOLEVERBVtbl };
1053
1054 static HRESULT WINAPI Test_IUnknown_QueryInterface(
1055 IUnknown *iface,
1056 REFIID riid,
1057 LPVOID *ppvObj)
1058 {
1059 if (ppvObj == NULL) return E_POINTER;
1060
1061 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IWineTest)) {
1062 *ppvObj = iface;
1063 }else if(IsEqualIID(riid, &IID_IEnumOLEVERB)) {
1064 *ppvObj = &EnumOLEVERB;
1065 }else {
1066 *ppvObj = NULL;
1067 return E_NOINTERFACE;
1068 }
1069
1070 IUnknown_AddRef((IUnknown*)*ppvObj);
1071 return S_OK;
1072 }
1073
1074 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
1075 {
1076 return 2; /* non-heap-based object */
1077 }
1078
1079 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
1080 {
1081 return 1; /* non-heap-based object */
1082 }
1083
1084 static const IUnknownVtbl TestUnknown_Vtbl =
1085 {
1086 Test_IUnknown_QueryInterface,
1087 Test_IUnknown_AddRef,
1088 Test_IUnknown_Release,
1089 };
1090
1091 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
1092
1093 static IPSFactoryBuffer *ps_factory_buffer;
1094
1095 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
1096 IPSFactoryBuffer * This,
1097 /* [in] */ REFIID riid,
1098 /* [iid_is][out] */ void **ppvObject)
1099 {
1100 if (IsEqualIID(riid, &IID_IUnknown) ||
1101 IsEqualIID(riid, &IID_IPSFactoryBuffer))
1102 {
1103 *ppvObject = This;
1104 IPSFactoryBuffer_AddRef(This);
1105 return S_OK;
1106 }
1107 return E_NOINTERFACE;
1108 }
1109
1110 static ULONG WINAPI PSFactoryBuffer_AddRef(
1111 IPSFactoryBuffer * This)
1112 {
1113 return 2;
1114 }
1115
1116 static ULONG WINAPI PSFactoryBuffer_Release(
1117 IPSFactoryBuffer * This)
1118 {
1119 return 1;
1120 }
1121
1122 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
1123 IPSFactoryBuffer * This,
1124 /* [in] */ IUnknown *pUnkOuter,
1125 /* [in] */ REFIID riid,
1126 /* [out] */ IRpcProxyBuffer **ppProxy,
1127 /* [out] */ void **ppv)
1128 {
1129 return E_NOTIMPL;
1130 }
1131
1132 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
1133 IPSFactoryBuffer * This,
1134 /* [in] */ REFIID riid,
1135 /* [unique][in] */ IUnknown *pUnkServer,
1136 /* [out] */ IRpcStubBuffer **ppStub)
1137 {
1138 CHECK_EXPECT(CreateStub);
1139
1140 ok(pUnkServer == (IUnknown*)&Test_Unknown, "unexpected pUnkServer %p\n", pUnkServer);
1141 if(!ps_factory_buffer)
1142 return E_NOTIMPL;
1143
1144 return IPSFactoryBuffer_CreateStub(ps_factory_buffer, &IID_IEnumOLEVERB, pUnkServer, ppStub);
1145 }
1146
1147 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
1148 {
1149 PSFactoryBuffer_QueryInterface,
1150 PSFactoryBuffer_AddRef,
1151 PSFactoryBuffer_Release,
1152 PSFactoryBuffer_CreateProxy,
1153 PSFactoryBuffer_CreateStub
1154 };
1155
1156 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
1157
1158 static const CLSID CLSID_WineTestPSFactoryBuffer =
1159 {
1160 0x52011640,
1161 0x8164,
1162 0x4fd0,
1163 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1164 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
1165
1166 static void test_CoRegisterPSClsid(void)
1167 {
1168 HRESULT hr;
1169 DWORD dwRegistrationKey;
1170 IStream *stream;
1171 CLSID clsid;
1172
1173 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1174 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1175
1176 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1177
1178 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
1179 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
1180 ok_ole_success(hr, "CoRegisterClassObject");
1181
1182 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1183 ok_ole_success(hr, "CoRegisterPSClsid");
1184
1185 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1186 ok_ole_success(hr, "CreateStreamOnHGlobal");
1187
1188 SET_EXPECT(CreateStub);
1189 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1190 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1191 CHECK_CALLED(CreateStub);
1192
1193 hr = CoGetPSClsid(&IID_IEnumOLEVERB, &clsid);
1194 ok_ole_success(hr, "CoGetPSClsid");
1195
1196 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void **)&ps_factory_buffer);
1197 ok_ole_success(hr, "CoGetClassObject");
1198
1199 hr = CoRegisterPSClsid(&IID_IEnumOLEVERB, &CLSID_WineTestPSFactoryBuffer);
1200 ok_ole_success(hr, "CoRegisterPSClsid");
1201
1202 SET_EXPECT(CreateStub);
1203 hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1204 ok(hr == S_OK, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1205 CHECK_CALLED(CreateStub);
1206
1207 hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1208 ok(hr == S_OK, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1209
1210 IStream_Release(stream);
1211 IPSFactoryBuffer_Release(ps_factory_buffer);
1212 ps_factory_buffer = NULL;
1213
1214 hr = CoRevokeClassObject(dwRegistrationKey);
1215 ok_ole_success(hr, "CoRevokeClassObject");
1216
1217 CoUninitialize();
1218
1219 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1220
1221 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1222 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
1223
1224 CoUninitialize();
1225 }
1226
1227 static void test_CoGetPSClsid(void)
1228 {
1229 ULONG_PTR cookie;
1230 HANDLE handle;
1231 HRESULT hr;
1232 CLSID clsid;
1233 HKEY hkey;
1234 LONG res;
1235 const BOOL is_win64 = (sizeof(void*) != sizeof(int));
1236 BOOL is_wow64 = FALSE;
1237
1238 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1239 ok(hr == CO_E_NOTINITIALIZED,
1240 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
1241 hr);
1242
1243 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1244
1245 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1246 ok_ole_success(hr, "CoGetPSClsid");
1247
1248 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1249 ok(hr == REGDB_E_IIDNOTREG,
1250 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
1251 hr);
1252
1253 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
1254 ok(hr == E_INVALIDARG,
1255 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
1256 hr);
1257
1258 if (!pRegOverridePredefKey)
1259 {
1260 win_skip("RegOverridePredefKey not available\n");
1261 CoUninitialize();
1262 return;
1263 }
1264 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1265 ok_ole_success(hr, "CoGetPSClsid");
1266
1267 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
1268 KEY_ALL_ACCESS, NULL, &hkey, NULL);
1269 ok(!res, "RegCreateKeyEx returned %d\n", res);
1270
1271 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
1272 ok(!res, "RegOverridePredefKey returned %d\n", res);
1273
1274 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1275 ok_ole_success(hr, "CoGetPSClsid");
1276
1277 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
1278 ok(!res, "RegOverridePredefKey returned %d\n", res);
1279
1280 RegCloseKey(hkey);
1281
1282 /* not registered CLSID */
1283 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1284 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1285
1286 if ((handle = activate_context(actctx_manifest, &cookie)))
1287 {
1288 memset(&clsid, 0, sizeof(clsid));
1289 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1290 ok(hr == S_OK, "got 0x%08x\n", hr);
1291 ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1292
1293 memset(&clsid, 0, sizeof(clsid));
1294 hr = CoGetPSClsid(&IID_Testiface2, &clsid);
1295 ok(hr == S_OK, "got 0x%08x\n", hr);
1296 ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1297
1298 memset(&clsid, 0, sizeof(clsid));
1299 hr = CoGetPSClsid(&IID_Testiface3, &clsid);
1300 ok(hr == S_OK, "got 0x%08x\n", hr);
1301 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1302
1303 memset(&clsid, 0xaa, sizeof(clsid));
1304 hr = CoGetPSClsid(&IID_Testiface4, &clsid);
1305 ok(hr == S_OK, "got 0x%08x\n", hr);
1306 ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1307
1308 /* register same interface and try to get CLSID back */
1309 hr = CoRegisterPSClsid(&IID_Testiface, &IID_Testiface4);
1310 ok(hr == S_OK, "got 0x%08x\n", hr);
1311 memset(&clsid, 0, sizeof(clsid));
1312 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1313 ok(hr == S_OK, "got 0x%08x\n", hr);
1314 ok(IsEqualGUID(&clsid, &IID_Testiface4), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1315
1316 pDeactivateActCtx(0, cookie);
1317 pReleaseActCtx(handle);
1318 }
1319
1320 if (pRegDeleteKeyExA &&
1321 (is_win64 ||
1322 (pIsWow64Process && pIsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
1323 {
1324 static GUID IID_DeadBeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1325 static const char clsidDeadBeef[] = "{deadbeef-dead-beef-dead-beefdeadbeef}";
1326 static const char clsidA[] = "{66666666-8888-7777-6666-555555555555}";
1327 HKEY hkey_iface, hkey_psclsid;
1328 REGSAM opposite = is_win64 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
1329
1330 hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1331 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1332
1333 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, "Interface",
1334 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_iface, NULL);
1335 ok(!res, "RegCreateKeyEx returned %d\n", res);
1336 res = RegCreateKeyExA(hkey_iface, clsidDeadBeef,
1337 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey, NULL);
1338 if (res == ERROR_ACCESS_DENIED)
1339 {
1340 win_skip("Failed to create a key, skipping some of CoGetPSClsid() tests\n");
1341 goto cleanup;
1342 }
1343
1344 ok(!res, "RegCreateKeyEx returned %d\n", res);
1345 res = RegCreateKeyExA(hkey, "ProxyStubClsid32",
1346 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_psclsid, NULL);
1347 ok(!res, "RegCreateKeyEx returned %d\n", res);
1348 res = RegSetValueExA(hkey_psclsid, NULL, 0, REG_SZ, (const BYTE *)clsidA, strlen(clsidA)+1);
1349 ok(!res, "RegSetValueEx returned %d\n", res);
1350 RegCloseKey(hkey_psclsid);
1351
1352 hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1353 ok_ole_success(hr, "CoGetPSClsid");
1354 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1355
1356 res = pRegDeleteKeyExA(hkey, "ProxyStubClsid32", opposite, 0);
1357 ok(!res, "RegDeleteKeyEx returned %d\n", res);
1358 RegCloseKey(hkey);
1359 res = pRegDeleteKeyExA(hkey_iface, clsidDeadBeef, opposite, 0);
1360 ok(!res, "RegDeleteKeyEx returned %d\n", res);
1361
1362 cleanup:
1363 RegCloseKey(hkey_iface);
1364 }
1365
1366 CoUninitialize();
1367 }
1368
1369 /* basic test, mainly for invalid arguments. see marshal.c for more */
1370 static void test_CoUnmarshalInterface(void)
1371 {
1372 IUnknown *pProxy;
1373 IStream *pStream;
1374 HRESULT hr;
1375
1376 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
1377 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1378
1379 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1380 ok_ole_success(hr, "CreateStreamOnHGlobal");
1381
1382 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1383 todo_wine
1384 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1385
1386 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1387
1388 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1389 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1390
1391 CoUninitialize();
1392
1393 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
1394 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1395
1396 IStream_Release(pStream);
1397 }
1398
1399 static void test_CoGetInterfaceAndReleaseStream(void)
1400 {
1401 HRESULT hr;
1402 IUnknown *pUnk;
1403
1404 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1405
1406 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
1407 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
1408
1409 CoUninitialize();
1410 }
1411
1412 /* basic test, mainly for invalid arguments. see marshal.c for more */
1413 static void test_CoMarshalInterface(void)
1414 {
1415 IStream *pStream;
1416 HRESULT hr;
1417 static const LARGE_INTEGER llZero;
1418
1419 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1420
1421 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1422 ok_ole_success(hr, "CreateStreamOnHGlobal");
1423
1424 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1425 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1426
1427 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1428 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1429
1430 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1431 ok_ole_success(hr, "CoMarshalInterface");
1432
1433 /* stream not rewound */
1434 hr = CoReleaseMarshalData(pStream);
1435 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1436
1437 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1438 ok_ole_success(hr, "IStream_Seek");
1439
1440 hr = CoReleaseMarshalData(pStream);
1441 ok_ole_success(hr, "CoReleaseMarshalData");
1442
1443 IStream_Release(pStream);
1444
1445 CoUninitialize();
1446 }
1447
1448 static void test_CoMarshalInterThreadInterfaceInStream(void)
1449 {
1450 IStream *pStream;
1451 HRESULT hr;
1452 IClassFactory *pProxy;
1453
1454 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1455
1456 cLocks = 0;
1457
1458 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
1459 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1460
1461 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
1462 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1463
1464 ok_no_locks();
1465
1466 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
1467 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
1468
1469 ok_more_than_one_lock();
1470
1471 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1472 ok_ole_success(hr, "CoUnmarshalInterface");
1473
1474 IClassFactory_Release(pProxy);
1475 IStream_Release(pStream);
1476
1477 ok_no_locks();
1478
1479 CoUninitialize();
1480 }
1481
1482 static void test_CoRegisterClassObject(void)
1483 {
1484 ULONG_PTR ctxcookie;
1485 HANDLE handle;
1486 DWORD cookie;
1487 HRESULT hr;
1488 IClassFactory *pcf;
1489
1490 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1491
1492 /* CLSCTX_INPROC_SERVER */
1493 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1494 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1495 ok_ole_success(hr, "CoRegisterClassObject");
1496 hr = CoRevokeClassObject(cookie);
1497 ok_ole_success(hr, "CoRevokeClassObject");
1498
1499 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1500 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1501 ok_ole_success(hr, "CoRegisterClassObject");
1502 hr = CoRevokeClassObject(cookie);
1503 ok_ole_success(hr, "CoRevokeClassObject");
1504
1505 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1506 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1507 ok_ole_success(hr, "CoRegisterClassObject");
1508 hr = CoRevokeClassObject(cookie);
1509 ok_ole_success(hr, "CoRevokeClassObject");
1510
1511 /* CLSCTX_LOCAL_SERVER */
1512 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1513 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1514 ok_ole_success(hr, "CoRegisterClassObject");
1515 hr = CoRevokeClassObject(cookie);
1516 ok_ole_success(hr, "CoRevokeClassObject");
1517
1518 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1519 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1520 ok_ole_success(hr, "CoRegisterClassObject");
1521 hr = CoRevokeClassObject(cookie);
1522 ok_ole_success(hr, "CoRevokeClassObject");
1523
1524 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1525 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1526 ok_ole_success(hr, "CoRegisterClassObject");
1527 hr = CoRevokeClassObject(cookie);
1528 ok_ole_success(hr, "CoRevokeClassObject");
1529
1530 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
1531 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1532 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1533 ok_ole_success(hr, "CoRegisterClassObject");
1534 hr = CoRevokeClassObject(cookie);
1535 ok_ole_success(hr, "CoRevokeClassObject");
1536
1537 /* test whether an object that doesn't support IClassFactory can be
1538 * registered for CLSCTX_LOCAL_SERVER */
1539 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
1540 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1541 ok_ole_success(hr, "CoRegisterClassObject");
1542 hr = CoRevokeClassObject(cookie);
1543 ok_ole_success(hr, "CoRevokeClassObject");
1544
1545 /* test whether registered class becomes invalid when apartment is destroyed */
1546 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1547 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1548 ok_ole_success(hr, "CoRegisterClassObject");
1549
1550 CoUninitialize();
1551 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1552
1553 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
1554 &IID_IClassFactory, (void **)&pcf);
1555 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
1556
1557 /* crashes with at least win9x DCOM! */
1558 if (0)
1559 CoRevokeClassObject(cookie);
1560
1561 /* test that object is accessible */
1562 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER,
1563 REGCLS_MULTIPLEUSE, &cookie);
1564 ok(hr == S_OK, "got 0x%08x\n", hr);
1565
1566 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1567 ok(hr == S_OK, "got 0x%08x\n", hr);
1568 IClassFactory_Release(pcf);
1569
1570 /* context now contains CLSID_WineOOPTest, test if registered one could still be used */
1571 if ((handle = activate_context(actctx_manifest, &ctxcookie)))
1572 {
1573 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1574 todo_wine
1575 ok(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), "got 0x%08x\n", hr);
1576
1577 pDeactivateActCtx(0, ctxcookie);
1578 pReleaseActCtx(handle);
1579 }
1580
1581 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1582 ok(hr == S_OK, "got 0x%08x\n", hr);
1583 IClassFactory_Release(pcf);
1584
1585 hr = CoRevokeClassObject(cookie);
1586 ok(hr == S_OK, "got 0x%08x\n", hr);
1587
1588 CoUninitialize();
1589 }
1590
1591 static HRESULT get_class_object(CLSCTX clsctx)
1592 {
1593 HRESULT hr;
1594 IClassFactory *pcf;
1595
1596 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1597 (void **)&pcf);
1598
1599 if (SUCCEEDED(hr))
1600 IClassFactory_Release(pcf);
1601
1602 return hr;
1603 }
1604
1605 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1606 {
1607 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1608 HRESULT hr;
1609
1610 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1611
1612 hr = get_class_object(clsctx);
1613
1614 CoUninitialize();
1615
1616 return hr;
1617 }
1618
1619 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1620 {
1621 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1622 HRESULT hr;
1623 IClassFactory *pcf;
1624 IMultiQI *pMQI;
1625
1626 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1627
1628 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1629 (void **)&pcf);
1630
1631 if (SUCCEEDED(hr))
1632 {
1633 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1634 if (SUCCEEDED(hr))
1635 IMultiQI_Release(pMQI);
1636 IClassFactory_Release(pcf);
1637 }
1638
1639 CoUninitialize();
1640
1641 return hr;
1642 }
1643
1644 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1645 {
1646 HRESULT hr;
1647 DWORD cookie;
1648
1649 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1650
1651 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1652 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1653
1654 CoUninitialize();
1655
1656 return hr;
1657 }
1658
1659 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1660 {
1661 DWORD cookie = (DWORD_PTR)pv;
1662 HRESULT hr;
1663
1664 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1665
1666 hr = CoRevokeClassObject(cookie);
1667
1668 CoUninitialize();
1669
1670 return hr;
1671 }
1672
1673 static void test_registered_object_thread_affinity(void)
1674 {
1675 HRESULT hr;
1676 DWORD cookie;
1677 HANDLE thread;
1678 DWORD tid;
1679 DWORD exitcode;
1680
1681 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1682
1683 /* CLSCTX_INPROC_SERVER */
1684
1685 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1686 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1687 ok_ole_success(hr, "CoRegisterClassObject");
1688
1689 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1690 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1691 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1692 GetExitCodeThread(thread, &exitcode);
1693 hr = exitcode;
1694 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1695 "registered in different thread should return REGDB_E_CLASSNOTREG "
1696 "instead of 0x%08x\n", hr);
1697
1698 hr = get_class_object(CLSCTX_INPROC_SERVER);
1699 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1700 "thread should return S_OK instead of 0x%08x\n", hr);
1701
1702 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1703 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1704 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1705 GetExitCodeThread(thread, &exitcode);
1706 hr = exitcode;
1707 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1708
1709 hr = CoRevokeClassObject(cookie);
1710 ok_ole_success(hr, "CoRevokeClassObject");
1711
1712 /* CLSCTX_LOCAL_SERVER */
1713
1714 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1715 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1716 ok_ole_success(hr, "CoRegisterClassObject");
1717
1718 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1719 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1720 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1721 {
1722 MSG msg;
1723 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1724 {
1725 TranslateMessage(&msg);
1726 DispatchMessageA(&msg);
1727 }
1728 }
1729 GetExitCodeThread(thread, &exitcode);
1730 hr = exitcode;
1731 ok(hr == S_OK, "CoGetClassObject on local server object "
1732 "registered in different thread should return S_OK "
1733 "instead of 0x%08x\n", hr);
1734
1735 hr = get_class_object(CLSCTX_LOCAL_SERVER);
1736 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1737 "thread should return S_OK instead of 0x%08x\n", hr);
1738
1739 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid);
1740 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1741 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1742 GetExitCodeThread(thread, &exitcode);
1743 hr = exitcode;
1744 ok(hr == RPC_E_WRONG_THREAD || broken(hr == S_OK) /* win8 */, "CoRevokeClassObject called from different "
1745 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1746
1747 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1748 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1749 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1750 GetExitCodeThread(thread, &exitcode);
1751 hr = exitcode;
1752 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1753 "thread should return S_OK instead of 0x%08x\n", hr);
1754
1755 hr = CoRevokeClassObject(cookie);
1756 ok_ole_success(hr, "CoRevokeClassObject");
1757
1758 CoUninitialize();
1759 }
1760
1761 static DWORD CALLBACK free_libraries_thread(LPVOID p)
1762 {
1763 CoFreeUnusedLibraries();
1764 return 0;
1765 }
1766
1767 static inline BOOL is_module_loaded(const char *module)
1768 {
1769 return GetModuleHandleA(module) != 0;
1770 }
1771
1772 static void test_CoFreeUnusedLibraries(void)
1773 {
1774 HRESULT hr;
1775 IUnknown *pUnk;
1776 DWORD tid;
1777 HANDLE thread;
1778
1779 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1780
1781 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1782
1783 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1784 if (hr == REGDB_E_CLASSNOTREG)
1785 {
1786 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1787 CoUninitialize();
1788 return;
1789 }
1790 ok_ole_success(hr, "CoCreateInstance");
1791
1792 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1793
1794 ok(pUnk != NULL ||
1795 broken(pUnk == NULL), /* win9x */
1796 "Expected a valid pointer\n");
1797 if (pUnk)
1798 IUnknown_Release(pUnk);
1799
1800 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1801
1802 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1803 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1804 CloseHandle(thread);
1805
1806 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1807
1808 CoFreeUnusedLibraries();
1809
1810 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1811
1812 CoUninitialize();
1813 }
1814
1815 static void test_CoGetObjectContext(void)
1816 {
1817 HRESULT hr;
1818 ULONG refs;
1819 IComThreadingInfo *pComThreadingInfo, *threadinginfo2;
1820 IContextCallback *pContextCallback;
1821 IObjContext *pObjContext;
1822 APTTYPE apttype;
1823 THDTYPE thdtype;
1824 struct info info;
1825 HANDLE thread;
1826 DWORD tid, exitcode;
1827 GUID id, id2;
1828
1829 if (!pCoGetObjectContext)
1830 {
1831 win_skip("CoGetObjectContext not present\n");
1832 return;
1833 }
1834
1835 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1836 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1837 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1838
1839 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1840 thread has already done so */
1841
1842 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
1843
1844 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
1845 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1846
1847 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
1848 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1849
1850 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1851 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1852
1853 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1854
1855 test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA, TRUE, TRUE);
1856
1857 pComThreadingInfo = NULL;
1858 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1859 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1860
1861 threadinginfo2 = NULL;
1862 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&threadinginfo2);
1863 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1864 ok(pComThreadingInfo == threadinginfo2, "got different instance\n");
1865 IComThreadingInfo_Release(threadinginfo2);
1866
1867 hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, NULL);
1868 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1869
1870 id = id2 = GUID_NULL;
1871 hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, &id);
1872 ok(hr == S_OK, "got 0x%08x\n", hr);
1873
1874 hr = CoGetCurrentLogicalThreadId(&id2);
1875 ok(IsEqualGUID(&id, &id2), "got %s, expected %s\n", wine_dbgstr_guid(&id), wine_dbgstr_guid(&id2));
1876
1877 IComThreadingInfo_Release(pComThreadingInfo);
1878
1879 SetEvent(info.stop);
1880 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1881
1882 GetExitCodeThread(thread, &exitcode);
1883 hr = exitcode;
1884 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1885
1886 CloseHandle(thread);
1887 CloseHandle(info.wait);
1888 CloseHandle(info.stop);
1889
1890 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
1891
1892 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1893
1894 test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
1895
1896 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1897 ok_ole_success(hr, "CoGetObjectContext");
1898
1899 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1900 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1901 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1902
1903 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1904 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1905 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1906
1907 refs = IComThreadingInfo_Release(pComThreadingInfo);
1908 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1909
1910 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1911 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1912
1913 refs = IContextCallback_Release(pContextCallback);
1914 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1915
1916 CoUninitialize();
1917
1918 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1919
1920 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1921 ok_ole_success(hr, "CoGetObjectContext");
1922
1923 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1924 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1925 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1926
1927 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1928 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1929 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1930
1931 refs = IComThreadingInfo_Release(pComThreadingInfo);
1932 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1933
1934 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1935 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1936
1937 refs = IContextCallback_Release(pContextCallback);
1938 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1939
1940 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1941 ok_ole_success(hr, "CoGetObjectContext");
1942
1943 refs = IObjContext_Release(pObjContext);
1944 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
1945
1946 CoUninitialize();
1947 }
1948
1949 typedef struct {
1950 IUnknown IUnknown_iface;
1951 LONG refs;
1952 } Test_CallContext;
1953
1954 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
1955 {
1956 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
1957 }
1958
1959 static HRESULT WINAPI Test_CallContext_QueryInterface(
1960 IUnknown *iface,
1961 REFIID riid,
1962 LPVOID *ppvObj)
1963 {
1964 if (ppvObj == NULL) return E_POINTER;
1965
1966 if (IsEqualGUID(riid, &IID_IUnknown))
1967 {
1968 *ppvObj = iface;
1969 IUnknown_AddRef(iface);
1970 return S_OK;
1971 }
1972
1973 *ppvObj = NULL;
1974 return E_NOINTERFACE;
1975 }
1976
1977 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
1978 {
1979 Test_CallContext *This = impl_from_IUnknown(iface);
1980 return InterlockedIncrement(&This->refs);
1981 }
1982
1983 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
1984 {
1985 Test_CallContext *This = impl_from_IUnknown(iface);
1986 ULONG refs = InterlockedDecrement(&This->refs);
1987 if (!refs)
1988 HeapFree(GetProcessHeap(), 0, This);
1989 return refs;
1990 }
1991
1992 static const IUnknownVtbl TestCallContext_Vtbl =
1993 {
1994 Test_CallContext_QueryInterface,
1995 Test_CallContext_AddRef,
1996 Test_CallContext_Release
1997 };
1998
1999 static void test_CoGetCallContext(void)
2000 {
2001 HRESULT hr;
2002 ULONG refs;
2003 IUnknown *pUnk;
2004 Test_CallContext *test_object;
2005
2006 if (!pCoSwitchCallContext)
2007 {
2008 skip("CoSwitchCallContext not present\n");
2009 return;
2010 }
2011
2012 CoInitialize(NULL);
2013
2014 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
2015 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
2016 test_object->refs = 1;
2017
2018 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
2019 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
2020
2021 pUnk = (IUnknown*)0xdeadbeef;
2022 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
2023 ok_ole_success(hr, "CoSwitchCallContext");
2024 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
2025 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
2026 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
2027 IUnknown_Release(&test_object->IUnknown_iface);
2028
2029 pUnk = (IUnknown*)0xdeadbeef;
2030 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
2031 ok_ole_success(hr, "CoGetCallContext");
2032 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
2033 &test_object->IUnknown_iface, pUnk);
2034 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
2035 ok(refs == 3, "Expected refcount 3, got %d\n", refs);
2036 IUnknown_Release(&test_object->IUnknown_iface);
2037 IUnknown_Release(pUnk);
2038
2039 pUnk = (IUnknown*)0xdeadbeef;
2040 hr = pCoSwitchCallContext(NULL, &pUnk);
2041 ok_ole_success(hr, "CoSwitchCallContext");
2042 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
2043 &test_object->IUnknown_iface, pUnk);
2044 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
2045 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
2046 IUnknown_Release(&test_object->IUnknown_iface);
2047
2048 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
2049 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
2050
2051 IUnknown_Release(&test_object->IUnknown_iface);
2052
2053 CoUninitialize();
2054 }
2055
2056 static void test_CoGetContextToken(void)
2057 {
2058 HRESULT hr;
2059 ULONG refs;
2060 ULONG_PTR token, token2;
2061 IObjContext *ctx;
2062 struct info info;
2063 HANDLE thread;
2064 DWORD tid, exitcode;
2065
2066 if (!pCoGetContextToken)
2067 {
2068 win_skip("CoGetContextToken not present\n");
2069 return;
2070 }
2071
2072 token = 0xdeadbeef;
2073 hr = pCoGetContextToken(&token);
2074 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
2075 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
2076
2077 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
2078 thread has already done so */
2079
2080 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
2081
2082 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
2083 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
2084
2085 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
2086 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
2087
2088 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
2089 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
2090
2091 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
2092
2093 test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA, TRUE, TRUE);
2094
2095 token = 0;
2096 hr = pCoGetContextToken(&token);
2097 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2098
2099 token2 = 0;
2100 hr = pCoGetContextToken(&token2);
2101 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2102 ok(token == token2, "got different token\n");
2103
2104 SetEvent(info.stop);
2105 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2106
2107 GetExitCodeThread(thread, &exitcode);
2108 hr = exitcode;
2109 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
2110
2111 CloseHandle(thread);
2112 CloseHandle(info.wait);
2113 CloseHandle(info.stop);
2114
2115 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
2116
2117 CoInitialize(NULL);
2118
2119 test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE, FALSE, FALSE);
2120
2121 hr = pCoGetContextToken(NULL);
2122 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
2123
2124 token = 0;
2125 hr = pCoGetContextToken(&token);
2126 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2127 ok(token, "Expected token != 0\n");
2128
2129 token2 = 0;
2130 hr = pCoGetContextToken(&token2);
2131 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2132 ok(token2 == token, "got different token\n");
2133
2134 refs = IUnknown_AddRef((IUnknown *)token);
2135 ok(refs == 1, "Expected 1, got %u\n", refs);
2136
2137 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
2138 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2139 ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
2140
2141 refs = IObjContext_AddRef(ctx);
2142 ok(refs == 3, "Expected 3, got %u\n", refs);
2143
2144 refs = IObjContext_Release(ctx);
2145 ok(refs == 2, "Expected 2, got %u\n", refs);
2146
2147 refs = IUnknown_Release((IUnknown *)token);
2148 ok(refs == 1, "Expected 1, got %u\n", refs);
2149
2150 /* CoGetContextToken does not add a reference */
2151 token = 0;
2152 hr = pCoGetContextToken(&token);
2153 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2154 ok(token, "Expected token != 0\n");
2155 ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
2156
2157 refs = IObjContext_AddRef(ctx);
2158 ok(refs == 2, "Expected 1, got %u\n", refs);
2159
2160 refs = IObjContext_Release(ctx);
2161 ok(refs == 1, "Expected 0, got %u\n", refs);
2162
2163 refs = IObjContext_Release(ctx);
2164 ok(refs == 0, "Expected 0, got %u\n", refs);
2165
2166 CoUninitialize();
2167 }
2168
2169 static void test_TreatAsClass(void)
2170 {
2171 HRESULT hr;
2172 CLSID out;
2173 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
2174 static const char deadbeefA[] = "{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}";
2175 IInternetProtocol *pIP = NULL;
2176 HKEY clsidkey, deadbeefkey;
2177 LONG lr;
2178
2179 if (!pCoGetTreatAsClass)
2180 {
2181 win_skip("CoGetTreatAsClass not present\n");
2182 return;
2183 }
2184 hr = pCoGetTreatAsClass(&deadbeef,&out);
2185 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
2186 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
2187
2188 lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &clsidkey);
2189 ok(!lr, "Couldn't open CLSID key, error %d\n", lr);
2190
2191 lr = RegCreateKeyExA(clsidkey, deadbeefA, 0, NULL, 0, KEY_WRITE, NULL, &deadbeefkey, NULL);
2192 if (lr) {
2193 win_skip("CoGetTreatAsClass() tests will be skipped (failed to create a test key, error %d)\n", lr);
2194 RegCloseKey(clsidkey);
2195 return;
2196 }
2197
2198 hr = pCoTreatAsClass(&deadbeef, &deadbeef);
2199 ok(hr == REGDB_E_WRITEREGDB, "CoTreatAsClass gave wrong error: %08x\n", hr);
2200
2201 hr = pCoTreatAsClass(&deadbeef, &CLSID_FileProtocol);
2202 if(hr == REGDB_E_WRITEREGDB){
2203 win_skip("Insufficient privileges to use CoTreatAsClass\n");
2204 goto exit;
2205 }
2206 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
2207
2208 hr = pCoGetTreatAsClass(&deadbeef, &out);
2209 ok(hr == S_OK, "CoGetTreatAsClass failed: %08x\n",hr);
2210 ok(IsEqualGUID(&out, &CLSID_FileProtocol), "expected to get substituted clsid\n");
2211
2212 OleInitialize(NULL);
2213
2214 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2215 if(hr == REGDB_E_CLASSNOTREG)
2216 {
2217 win_skip("IE not installed so can't test CoCreateInstance\n");
2218 goto exit;
2219 }
2220
2221 ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
2222 if(pIP){
2223 IInternetProtocol_Release(pIP);
2224 pIP = NULL;
2225 }
2226
2227 hr = pCoTreatAsClass(&deadbeef, &CLSID_NULL);
2228 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
2229
2230 hr = pCoGetTreatAsClass(&deadbeef, &out);
2231 ok(hr == S_FALSE, "expected S_FALSE got %08x\n", hr);
2232 ok(IsEqualGUID(&out, &deadbeef), "expected to get same clsid back\n");
2233
2234 /* bizarrely, native's CoTreatAsClass takes some time to take effect in CoCreateInstance */
2235 Sleep(200);
2236
2237 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2238 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance gave wrong error: %08x\n", hr);
2239
2240 if(pIP)
2241 IInternetProtocol_Release(pIP);
2242
2243 exit:
2244 OleUninitialize();
2245 RegCloseKey(deadbeefkey);
2246 RegDeleteKeyA(clsidkey, deadbeefA);
2247 RegCloseKey(clsidkey);
2248 }
2249
2250 static void test_CoInitializeEx(void)
2251 {
2252 HRESULT hr;
2253
2254 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2255 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2256
2257 /* Calling OleInitialize for the first time should yield S_OK even with
2258 * apartment already initialized by previous CoInitialize(Ex) calls. */
2259 hr = OleInitialize(NULL);
2260 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
2261
2262 /* Subsequent calls to OleInitialize should return S_FALSE */
2263 hr = OleInitialize(NULL);
2264 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
2265
2266 /* Cleanup */
2267 CoUninitialize();
2268 OleUninitialize();
2269 OleUninitialize();
2270 }
2271
2272 static void test_OleInitialize_InitCounting(void)
2273 {
2274 HRESULT hr;
2275 IUnknown *pUnk;
2276 REFCLSID rclsid = &CLSID_InternetZoneManager;
2277
2278 /* 1. OleInitialize fails but OleUninitialize is still called: apartment stays initialized */
2279 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
2280 ok(hr == S_OK, "CoInitializeEx(COINIT_MULTITHREADED) failed with error 0x%08x\n", hr);
2281
2282 hr = OleInitialize(NULL);
2283 ok(hr == RPC_E_CHANGED_MODE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", RPC_E_CHANGED_MODE, hr);
2284 OleUninitialize();
2285
2286 pUnk = (IUnknown *)0xdeadbeef;
2287 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2288 ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2289 if (pUnk) IUnknown_Release(pUnk);
2290
2291 CoUninitialize();
2292
2293 /* 2. Extra multiple OleUninitialize: apartment stays initialized until CoUninitialize */
2294 hr = CoInitialize(NULL);
2295 ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
2296
2297 hr = OleInitialize(NULL);
2298 ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2299 OleUninitialize();
2300 OleUninitialize();
2301 OleUninitialize();
2302
2303 pUnk = (IUnknown *)0xdeadbeef;
2304 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2305 ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2306 if (pUnk) IUnknown_Release(pUnk);
2307
2308 CoUninitialize();
2309
2310 pUnk = (IUnknown *)0xdeadbeef;
2311 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2312 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
2313 if (pUnk) IUnknown_Release(pUnk);
2314
2315 /* 3. CoUninitialize does not formally deinit Ole */
2316 hr = CoInitialize(NULL);
2317 ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
2318
2319 hr = OleInitialize(NULL);
2320 ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2321
2322 CoUninitialize();
2323 CoUninitialize();
2324
2325 pUnk = (IUnknown *)0xdeadbeef;
2326 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2327 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
2328 /* COM is not initialized anymore */
2329 if (pUnk) IUnknown_Release(pUnk);
2330
2331 hr = OleInitialize(NULL);
2332 ok(hr == S_FALSE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_FALSE, hr);
2333 /* ... but native OleInit returns S_FALSE as if Ole is considered initialized */
2334
2335 OleUninitialize();
2336
2337 }
2338
2339 static void test_OleRegGetMiscStatus(void)
2340 {
2341 ULONG_PTR cookie;
2342 HANDLE handle;
2343 DWORD status;
2344 HRESULT hr;
2345
2346 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, NULL);
2347 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2348
2349 status = 0xdeadbeef;
2350 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2351 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
2352 ok(status == 0, "got 0x%08x\n", status);
2353
2354 status = -1;
2355 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2356 ok(hr == S_OK, "got 0x%08x\n", hr);
2357 ok(status == 0, "got 0x%08x\n", status);
2358
2359 if ((handle = activate_context(actctx_manifest, &cookie)))
2360 {
2361 status = 0;
2362 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2363 ok(hr == S_OK, "got 0x%08x\n", hr);
2364 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2365
2366 /* context data takes precedence over registration info */
2367 status = 0;
2368 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2369 ok(hr == S_OK, "got 0x%08x\n", hr);
2370 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2371
2372 /* there's no such attribute in context */
2373 status = -1;
2374 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status);
2375 ok(hr == S_OK, "got 0x%08x\n", hr);
2376 ok(status == 0, "got 0x%08x\n", status);
2377
2378 pDeactivateActCtx(0, cookie);
2379 pReleaseActCtx(handle);
2380 }
2381 }
2382
2383 static void test_OleRegGetUserType(void)
2384 {
2385 static const WCHAR stdfont_usertypeW[] = {'S','t','a','n','d','a','r','d',' ','F','o','n','t',0};
2386 static const WCHAR stdfont2_usertypeW[] = {'C','L','S','I','D','_','S','t','d','F','o','n','t',0};
2387 static const WCHAR clsidkeyW[] = {'C','L','S','I','D',0};
2388 static const WCHAR defvalueW[] = {'D','e','f','a','u','l','t',' ','N','a','m','e',0};
2389 static const WCHAR auxvalue0W[] = {'A','u','x',' ','N','a','m','e',' ','0',0};
2390 static const WCHAR auxvalue2W[] = {'A','u','x',' ','N','a','m','e',' ','2',0};
2391 static const WCHAR auxvalue3W[] = {'A','u','x',' ','N','a','m','e',' ','3',0};
2392 static const WCHAR auxvalue4W[] = {'A','u','x',' ','N','a','m','e',' ','4',0};
2393
2394 static const char auxvalues[][16] = {
2395 "Aux Name 0",
2396 "Aux Name 1",
2397 "Aux Name 2",
2398 "Aux Name 3",
2399 "Aux Name 4"
2400 };
2401
2402 HKEY clsidhkey, hkey, auxhkey, classkey;
2403 DWORD form, ret, disposition;
2404 WCHAR clsidW[39];
2405 ULONG_PTR cookie;
2406 HANDLE handle;
2407 HRESULT hr;
2408 WCHAR *str;
2409 int i;
2410
2411 for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) {
2412 hr = OleRegGetUserType(&CLSID_Testclass, form, NULL);
2413 ok(hr == E_INVALIDARG, "form %u: got 0x%08x\n", form, hr);
2414
2415 str = (void*)0xdeadbeef;
2416 hr = OleRegGetUserType(&CLSID_Testclass, form, &str);
2417 ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr);
2418 ok(str == NULL, "form %u: got %p\n", form, str);
2419
2420 /* same string returned for StdFont for all form types */
2421 str = NULL;
2422 hr = OleRegGetUserType(&CLSID_StdFont, form, &str);
2423 ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr);
2424 ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */,
2425 "form %u, got %s\n", form, wine_dbgstr_w(str));
2426 CoTaskMemFree(str);
2427 }
2428
2429 if ((handle = activate_context(actctx_manifest, &cookie)))
2430 {
2431 for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) {
2432 str = (void*)0xdeadbeef;
2433 hr = OleRegGetUserType(&CLSID_Testclass, form, &str);
2434 ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr);
2435 ok(str == NULL, "form %u: got %s\n", form, wine_dbgstr_w(str));
2436
2437 /* same string returned for StdFont for all form types */
2438 str = NULL;
2439 hr = OleRegGetUserType(&CLSID_StdFont, form, &str);
2440 ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr);
2441 ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */,
2442 "form %u, got %s\n", form, wine_dbgstr_w(str));
2443 CoTaskMemFree(str);
2444 }
2445
2446 pDeactivateActCtx(0, cookie);
2447 pReleaseActCtx(handle);
2448 }
2449
2450 /* test using registered CLSID */
2451 StringFromGUID2(&CLSID_non_existent, clsidW, sizeof(clsidW)/sizeof(clsidW[0]));
2452
2453 ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsidkeyW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &clsidhkey, &disposition);
2454 if (!ret)
2455 {
2456 ret = RegCreateKeyExW(clsidhkey, clsidW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &classkey, NULL);
2457 if (ret)
2458 RegCloseKey(clsidhkey);
2459 }
2460
2461 if (ret == ERROR_ACCESS_DENIED)
2462 {
2463 win_skip("Failed to create test key, skipping some of OleRegGetUserType() tests.\n");
2464 return;
2465 }
2466
2467 ok(!ret, "failed to create a key, error %d\n", ret);
2468
2469 ret = RegSetValueExW(classkey, NULL, 0, REG_SZ, (const BYTE*)defvalueW, sizeof(defvalueW));
2470 ok(!ret, "got error %d\n", ret);
2471
2472 ret = RegCreateKeyExA(classkey, "AuxUserType", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &auxhkey, NULL);
2473 ok(!ret, "got error %d\n", ret);
2474
2475 /* populate AuxUserType */
2476 for (i = 0; i <= 4; i++) {
2477 char name[16];
2478
2479 sprintf(name, "AuxUserType\\%d", i);
2480 ret = RegCreateKeyExA(classkey, name, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2481 ok(!ret, "got error %d\n", ret);
2482
2483 ret = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE*)auxvalues[i], strlen(auxvalues[i]));
2484 ok(!ret, "got error %d\n", ret);
2485 RegCloseKey(hkey);
2486 }
2487
2488 str = NULL;
2489 hr = OleRegGetUserType(&CLSID_non_existent, 0, &str);
2490 ok(hr == S_OK, "got 0x%08x\n", hr);
2491 ok(!lstrcmpW(str, auxvalue0W), "got %s\n", wine_dbgstr_w(str));
2492 CoTaskMemFree(str);
2493
2494 str = NULL;
2495 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_FULL, &str);
2496 ok(hr == S_OK, "got 0x%08x\n", hr);
2497 ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str));
2498 CoTaskMemFree(str);
2499
2500 str = NULL;
2501 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_SHORT, &str);
2502 ok(hr == S_OK, "got 0x%08x\n", hr);
2503 ok(!lstrcmpW(str, auxvalue2W), "got %s\n", wine_dbgstr_w(str));
2504 CoTaskMemFree(str);
2505
2506 str = NULL;
2507 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME, &str);
2508 ok(hr == S_OK, "got 0x%08x\n", hr);
2509 ok(!lstrcmpW(str, auxvalue3W), "got %s\n", wine_dbgstr_w(str));
2510 CoTaskMemFree(str);
2511
2512 str = NULL;
2513 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+1, &str);
2514 ok(hr == S_OK, "got 0x%08x\n", hr);
2515 ok(!lstrcmpW(str, auxvalue4W), "got %s\n", wine_dbgstr_w(str));
2516 CoTaskMemFree(str);
2517
2518 str = NULL;
2519 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+2, &str);
2520 ok(hr == S_OK, "got 0x%08x\n", hr);
2521 ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str));
2522 CoTaskMemFree(str);
2523
2524 /* registry cleanup */
2525 for (i = 0; i <= 4; i++)
2526 {
2527 char name[2];
2528 sprintf(name, "%d", i);
2529 RegDeleteKeyA(auxhkey, name);
2530 }
2531 RegCloseKey(auxhkey);
2532 RegDeleteKeyA(classkey, "AuxUserType");
2533 RegCloseKey(classkey);
2534 RegDeleteKeyW(clsidhkey, clsidW);
2535 RegCloseKey(clsidhkey);
2536 if (disposition == REG_CREATED_NEW_KEY)
2537 RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID");
2538 }
2539
2540 static void test_CoCreateGuid(void)
2541 {
2542 HRESULT hr;
2543
2544 hr = CoCreateGuid(NULL);
2545 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2546 }
2547
2548 static void CALLBACK apc_test_proc(ULONG_PTR param)
2549 {
2550 /* nothing */
2551 }
2552
2553 static DWORD CALLBACK release_semaphore_thread( LPVOID arg )
2554 {
2555 HANDLE handle = arg;
2556 if (WaitForSingleObject(handle, 200) == WAIT_TIMEOUT)
2557 ReleaseSemaphore(handle, 1, NULL);
2558 return 0;
2559 }
2560
2561 static DWORD CALLBACK send_message_thread(LPVOID arg)
2562 {
2563 HWND hWnd = arg;
2564 Sleep(50);
2565 SendMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2566 return 0;
2567 }
2568
2569 static DWORD CALLBACK post_message_thread(LPVOID arg)
2570 {
2571 HWND hWnd = arg;
2572 Sleep(50);
2573 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2574 return 0;
2575 }
2576
2577 static const char cls_name[] = "cowait_test_class";
2578 static DWORD CALLBACK test_CoWaitForMultipleHandles_thread(LPVOID arg)
2579 {
2580 HANDLE *handles = arg;
2581 BOOL success;
2582 DWORD index;
2583 HRESULT hr;
2584 HWND hWnd;
2585 MSG msg;
2586
2587 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2588 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2589
2590 hWnd = CreateWindowExA(0, cls_name, "Test (thread)", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2591 ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
2592
2593 index = 0xdeadbeef;
2594 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2595 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2596 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2597 ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index);
2598 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2599 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2600
2601 index = 0xdeadbeef;
2602 PostMessageA(hWnd, WM_USER, 0, 0);
2603 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2604 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2605 ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index);
2606 success = PeekMessageA(&msg, hWnd, WM_USER, WM_USER, PM_REMOVE);
2607 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2608
2609 DestroyWindow(hWnd);
2610 CoUninitialize();
2611 return 0;
2612 }
2613
2614 static void test_CoWaitForMultipleHandles(void)
2615 {
2616 HANDLE handles[2], thread;
2617 DWORD index, tid;
2618 WNDCLASSEXA wc;
2619 BOOL success;
2620 HRESULT hr;
2621 HWND hWnd;
2622 MSG msg;
2623
2624 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2625 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2626
2627 memset(&wc, 0, sizeof(wc));
2628 wc.cbSize = sizeof(wc);
2629 wc.style = CS_VREDRAW | CS_HREDRAW;
2630 wc.hInstance = GetModuleHandleA(0);
2631 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2632 wc.hbrBackground = NULL;
2633 wc.lpszClassName = cls_name;
2634 wc.lpfnWndProc = DefWindowProcA;
2635 success = RegisterClassExA(&wc) != 0;
2636 ok(success, "RegisterClassExA failed %u\n", GetLastError());
2637
2638 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2639 ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
2640 handles[0] = CreateSemaphoreA(NULL, 1, 1, NULL);
2641 ok(handles[0] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2642 handles[1] = CreateSemaphoreA(NULL, 1, 1, NULL);
2643 ok(handles[1] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2644
2645 /* test without flags */
2646
2647 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2648 hr = CoWaitForMultipleHandles(0, 50, 0, handles, NULL);
2649 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2650 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2651 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2652
2653 index = 0xdeadbeef;
2654 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2655 hr = CoWaitForMultipleHandles(0, 50, 0, NULL, &index);
2656 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2657 ok(index == 0, "expected index 0, got %u\n", index);
2658 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2659 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2660
2661 index = 0xdeadbeef;
2662 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2663 hr = CoWaitForMultipleHandles(0, 50, 0, handles, &index);
2664 ok(hr == RPC_E_NO_SYNC, "expected RPC_E_NO_SYNC, got 0x%08x\n", hr);
2665 ok(index == 0, "expected index 0, got %u\n", index);
2666 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2667 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2668
2669 index = 0xdeadbeef;
2670 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2671 hr = CoWaitForMultipleHandles(0, 50, 1, handles, &index);
2672 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2673 ok(index == 0, "expected index 0, got %u\n", index);
2674 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2675 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2676
2677 index = 0xdeadbeef;
2678 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2679 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2680 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2681 ok(index == 1, "expected index 1, got %u\n", index);
2682 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2683 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2684
2685 index = 0xdeadbeef;
2686 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2687 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2688 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2689 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2690 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2691 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2692
2693 /* test PostMessageA/SendMessageA from a different thread */
2694
2695 index = 0xdeadbeef;
2696 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2697 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2698 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2699 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2700 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2701 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2702 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2703 index = WaitForSingleObject(thread, 200);
2704 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2705 CloseHandle(thread);
2706
2707 index = 0xdeadbeef;
2708 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2709 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2710 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2711 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2712 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2713 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2714 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2715 index = WaitForSingleObject(thread, 200);
2716 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2717 CloseHandle(thread);
2718
2719 ReleaseSemaphore(handles[0], 1, NULL);
2720 ReleaseSemaphore(handles[1], 1, NULL);
2721
2722 /* test with COWAIT_WAITALL */
2723
2724 index = 0xdeadbeef;
2725 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2726 hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 50, 2, handles, &index);
2727 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2728 ok(index == 0, "expected index 0, got %u\n", index);
2729 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2730 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2731
2732 index = 0xdeadbeef;
2733 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2734 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2735 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2736 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2737 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2738 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2739
2740 ReleaseSemaphore(handles[0], 1, NULL);
2741 ReleaseSemaphore(handles[1], 1, NULL);
2742
2743 /* test with COWAIT_ALERTABLE */
2744
2745 index = 0xdeadbeef;
2746 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2747 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 1, handles, &index);
2748 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2749 ok(index == 0, "expected index 0, got %u\n", index);
2750 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2751 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2752
2753 index = 0xdeadbeef;
2754 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2755 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2756 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2757 ok(index == 1, "expected index 1, got %u\n", index);
2758 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2759 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2760
2761 index = 0xdeadbeef;
2762 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2763 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2764 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2765 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2766 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2767 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2768
2769 index = 0xdeadbeef;
2770 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2771 success = QueueUserAPC(apc_test_proc, GetCurrentThread(), 0);
2772 ok(success, "QueueUserAPC failed %u\n", GetLastError());
2773 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2774 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2775 ok(index == WAIT_IO_COMPLETION, "expected index WAIT_IO_COMPLETION, got %u\n", index);
2776 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2777 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2778
2779 /* test with COWAIT_INPUTAVAILABLE (semaphores are still locked) */
2780
2781 index = 0xdeadbeef;
2782 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2783 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2784 ok(success, "PeekMessageA returned FALSE\n");
2785 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2786 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2787 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2788 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2789 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2790
2791 index = 0xdeadbeef;
2792 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2793 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2794 ok(success, "PeekMessageA returned FALSE\n");
2795 thread = CreateThread(NULL, 0, release_semaphore_thread, handles[1], 0, &tid);
2796 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2797 hr = CoWaitForMultipleHandles(COWAIT_INPUTAVAILABLE, 50, 2, handles, &index);
2798 ok(hr == RPC_S_CALLPENDING || broken(hr == E_INVALIDARG) || broken(hr == S_OK) /* Win 8 */,
2799 "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2800 if (hr != S_OK) ReleaseSemaphore(handles[1], 1, NULL);
2801 ok(index == 0 || broken(index == 1) /* Win 8 */, "expected index 0, got %u\n", index);
2802 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2803 ok(!success || broken(success && hr == E_INVALIDARG),
2804 "CoWaitForMultipleHandles didn't pump any messages\n");
2805 index = WaitForSingleObject(thread, 200);
2806 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2807 CloseHandle(thread);
2808
2809 /* test behaviour of WM_QUIT (semaphores are still locked) */
2810
2811 PostMessageA(hWnd, WM_QUIT, 40, 0);
2812 memset(&msg, 0, sizeof(msg));
2813 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2814 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2815 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2816 ok(msg.wParam == 40, "expected msg.wParam = 40, got %lu\n", msg.wParam);
2817 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2818 ok(!success, "PeekMessageA succeeded\n");
2819
2820 index = 0xdeadbeef;
2821 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2822 PostMessageA(hWnd, WM_QUIT, 41, 0);
2823 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2824 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2825 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2826 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2827 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2828 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2829 todo_wine
2830 ok(success || broken(!success) /* Win 2000/XP/8 */, "PeekMessageA failed, error %u\n", GetLastError());
2831 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2832 ok(!success, "PeekMessageA succeeded\n");
2833 memset(&msg, 0, sizeof(msg));
2834 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2835 todo_wine
2836 ok(!success || broken(success) /* Win 2000/XP/8 */, "PeekMessageA succeeded\n");
2837 if (success)
2838 {
2839 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2840 ok(msg.wParam == 41, "expected msg.wParam = 41, got %lu\n", msg.wParam);
2841 }
2842 index = WaitForSingleObject(thread, 200);
2843 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2844 CloseHandle(thread);
2845
2846 index = 0xdeadbeef;
2847 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2848 PostMessageA(hWnd, WM_QUIT, 42, 0);
2849 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2850 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);
2853 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2854 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2855 ok(!success, "CoWaitForMultipleHandles didn't pump all WM_DDE_FIRST messages\n");
2856 memset(&msg, 0, sizeof(msg));
2857 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2858 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2859 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2860 ok(msg.wParam == 42, "expected msg.wParam = 42, got %lu\n", msg.wParam);
2861 index = WaitForSingleObject(thread, 200);
2862 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2863 CloseHandle(thread);
2864
2865 PostQuitMessage(43);
2866 memset(&msg, 0, sizeof(msg));
2867 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2868 ok(success || broken(!success) /* Win 8 */, "PeekMessageA failed, error %u\n", GetLastError());
2869 if (!success)
2870 win_skip("PostQuitMessage didn't queue a WM_QUIT message, skipping tests\n");
2871 else
2872 {
2873 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2874 ok(msg.wParam == 43, "expected msg.wParam = 43, got %lu\n", msg.wParam);
2875 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2876 ok(!success, "PeekMessageA succeeded\n");
2877
2878 index = 0xdeadbeef;
2879 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2880 PostQuitMessage(44);
2881 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2882 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2883 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2884 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2885 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2886 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2887 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2888 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2889 todo_wine
2890 ok(!success, "PeekMessageA succeeded\n");
2891 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2892 todo_wine
2893 ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n");
2894 index = WaitForSingleObject(thread, 200);
2895 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2896 CloseHandle(thread);
2897
2898 index = 0xdeadbeef;
2899 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2900 PostQuitMessage(45);
2901 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2902 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2903 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2904 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2905 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2906 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2907 ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2908 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2909 todo_wine
2910 ok(!success, "PeekMessageA succeeded\n");
2911 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2912 ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n");
2913 index = WaitForSingleObject(thread, 200);
2914 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2915 CloseHandle(thread);
2916 }
2917
2918 /* test message pumping when CoWaitForMultipleHandles is called from non main apartment thread */
2919 thread = CreateThread(NULL, 0, test_CoWaitForMultipleHandles_thread, handles, 0, &tid);
2920 index = WaitForSingleObject(thread, 500);
2921 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2922 CloseHandle(thread);
2923
2924 CloseHandle(handles[0]);
2925 CloseHandle(handles[1]);
2926 DestroyWindow(hWnd);
2927
2928 success = UnregisterClassA(cls_name, GetModuleHandleA(0));
2929 ok(success, "UnregisterClass failed %u\n", GetLastError());
2930
2931 CoUninitialize();
2932 }
2933
2934 static void test_CoGetMalloc(void)
2935 {
2936 IMalloc *imalloc;
2937 HRESULT hr;
2938
2939 if (0) /* crashes on native */
2940 hr = CoGetMalloc(0, NULL);
2941
2942 imalloc = (void*)0xdeadbeef;
2943 hr = CoGetMalloc(0, &imalloc);
2944 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2945 ok(imalloc == NULL, "got %p\n", imalloc);
2946
2947 imalloc = (void*)0xdeadbeef;
2948 hr = CoGetMalloc(MEMCTX_SHARED, &imalloc);
2949 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2950 ok(imalloc == NULL, "got %p\n", imalloc);
2951
2952 imalloc = (void*)0xdeadbeef;
2953 hr = CoGetMalloc(MEMCTX_MACSYSTEM, &imalloc);
2954 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2955 ok(imalloc == NULL, "got %p\n", imalloc);
2956
2957 imalloc = (void*)0xdeadbeef;
2958 hr = CoGetMalloc(MEMCTX_UNKNOWN, &imalloc);
2959 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2960 ok(imalloc == NULL, "got %p\n", imalloc);
2961
2962 imalloc = (void*)0xdeadbeef;
2963 hr = CoGetMalloc(MEMCTX_SAME, &imalloc);
2964 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2965 ok(imalloc == NULL, "got %p\n", imalloc);
2966
2967 imalloc = NULL;
2968 hr = CoGetMalloc(MEMCTX_TASK, &imalloc);
2969 ok(hr == S_OK, "got 0x%08x\n", hr);
2970 ok(imalloc != NULL, "got %p\n", imalloc);
2971 IMalloc_Release(imalloc);
2972 }
2973
2974 static void test_CoGetApartmentType(void)
2975 {
2976 APTTYPEQUALIFIER qualifier;
2977 APTTYPE type;
2978 HRESULT hr;
2979
2980 if (!pCoGetApartmentType)
2981 {
2982 win_skip("CoGetApartmentType not present\n");
2983 return;
2984 }
2985
2986 hr = pCoGetApartmentType(NULL, NULL);
2987 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
2988
2989 type = 0xdeadbeef;
2990 hr = pCoGetApartmentType(&type, NULL);
2991 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
2992 ok(type == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", type);
2993
2994 qualifier = 0xdeadbeef;
2995 hr = pCoGetApartmentType(NULL, &qualifier);
2996 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
2997 ok(qualifier == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", qualifier);
2998
2999 type = 0xdeadbeef;
3000 qualifier = 0xdeadbeef;
3001 hr = pCoGetApartmentType(&type, &qualifier);
3002 ok(hr == CO_E_NOTINITIALIZED, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3003 ok(type == APTTYPE_CURRENT, "Expected APTTYPE_CURRENT, got %u\n", type);
3004 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3005
3006 type = 0xdeadbeef;
3007 qualifier = 0xdeadbeef;
3008 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3009 ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr);
3010 hr = pCoGetApartmentType(&type, &qualifier);
3011 ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr);
3012 ok(type == APTTYPE_MAINSTA, "Expected APTTYPE_MAINSTA, got %u\n", type);
3013 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3014 CoUninitialize();
3015
3016 type = 0xdeadbeef;
3017 qualifier = 0xdeadbeef;
3018 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
3019 ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr);
3020 hr = pCoGetApartmentType(&type, &qualifier);
3021 ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr);
3022 ok(type == APTTYPE_MTA, "Expected APTTYPE_MTA, got %u\n", type);
3023 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3024 CoUninitialize();
3025 }
3026
3027 static HRESULT WINAPI testspy_QI(IMallocSpy *iface, REFIID riid, void **obj)
3028 {
3029 if (IsEqualIID(riid, &IID_IMallocSpy) || IsEqualIID(riid, &IID_IUnknown))
3030 {
3031 *obj = iface;
3032 IMallocSpy_AddRef(iface);
3033 return S_OK;
3034 }
3035
3036 return E_NOINTERFACE;
3037 }
3038
3039 static ULONG WINAPI testspy_AddRef(IMallocSpy *iface)
3040 {
3041 return 2;
3042 }
3043
3044 static ULONG WINAPI testspy_Release(IMallocSpy *iface)
3045 {
3046 return 1;
3047 }
3048
3049 static SIZE_T WINAPI testspy_PreAlloc(IMallocSpy *iface, SIZE_T cb)
3050 {
3051 ok(0, "unexpected call\n");
3052 return 0;
3053 }
3054
3055 static void* WINAPI testspy_PostAlloc(IMallocSpy *iface, void *ptr)
3056 {
3057 ok(0, "unexpected call\n");
3058 return NULL;
3059 }
3060
3061 static void* WINAPI testspy_PreFree(IMallocSpy *iface, void *ptr, BOOL spyed)
3062 {
3063 ok(0, "unexpected call\n");
3064 return NULL;
3065 }
3066
3067 static void WINAPI testspy_PostFree(IMallocSpy *iface, BOOL spyed)
3068 {
3069 ok(0, "unexpected call\n");
3070 }
3071
3072 static SIZE_T WINAPI testspy_PreRealloc(IMallocSpy *iface, void *ptr, SIZE_T cb, void **newptr, BOOL spyed)
3073 {
3074 ok(0, "unexpected call\n");
3075 return 0;
3076 }
3077
3078 static void* WINAPI testspy_PostRealloc(IMallocSpy *iface, void *ptr, BOOL spyed)
3079 {
3080 ok(0, "unexpected call\n");
3081 return NULL;
3082 }
3083
3084 static void* WINAPI testspy_PreGetSize(IMallocSpy *iface, void *ptr, BOOL spyed)
3085 {
3086 ok(0, "unexpected call\n");
3087 return NULL;
3088 }
3089
3090 static SIZE_T WINAPI testspy_PostGetSize(IMallocSpy *iface, SIZE_T actual, BOOL spyed)
3091 {
3092 ok(0, "unexpected call\n");
3093 return 0;
3094 }
3095
3096 static void* WINAPI testspy_PreDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed)
3097 {
3098 ok(0, "unexpected call\n");
3099 return NULL;
3100 }
3101
3102 static int WINAPI testspy_PostDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed, int actual)
3103 {
3104 ok(0, "unexpected call\n");
3105 return 0;
3106 }
3107
3108 static void WINAPI testspy_PreHeapMinimize(IMallocSpy *iface)
3109 {
3110 ok(0, "unexpected call\n");
3111 }
3112
3113 static void WINAPI testspy_PostHeapMinimize(IMallocSpy *iface)
3114 {
3115 ok(0, "unexpected call\n");
3116 }
3117
3118 static const IMallocSpyVtbl testspyvtbl =
3119 {
3120 testspy_QI,
3121 testspy_AddRef,
3122 testspy_Release,
3123 testspy_PreAlloc,
3124 testspy_PostAlloc,
3125 testspy_PreFree,
3126 testspy_PostFree,
3127 testspy_PreRealloc,
3128 testspy_PostRealloc,
3129 testspy_PreGetSize,
3130 testspy_PostGetSize,
3131 testspy_PreDidAlloc,
3132 testspy_PostDidAlloc,
3133 testspy_PreHeapMinimize,
3134 testspy_PostHeapMinimize
3135 };
3136
3137 static IMallocSpy testspy = { &testspyvtbl };
3138
3139 static void test_IMallocSpy(void)
3140 {
3141 IMalloc *imalloc;
3142 HRESULT hr;
3143
3144 hr = CoRegisterMallocSpy(NULL);
3145 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3146
3147 hr = CoRevokeMallocSpy();
3148 ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr);
3149
3150 hr = CoRegisterMallocSpy(&testspy);
3151 ok(hr == S_OK, "got 0x%08x\n", hr);
3152
3153 hr = CoRegisterMallocSpy(NULL);
3154 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3155
3156 hr = CoRegisterMallocSpy(&testspy);
3157 ok(hr == CO_E_OBJISREG, "got 0x%08x\n", hr);
3158
3159 imalloc = NULL;
3160 hr = CoGetMalloc(MEMCTX_TASK, &imalloc);
3161 ok(hr == S_OK, "got 0x%08x\n", hr);
3162 ok(imalloc != NULL, "got %p\n", imalloc);
3163
3164 IMalloc_Free(imalloc, NULL);
3165
3166 IMalloc_Release(imalloc);
3167
3168 hr = CoRevokeMallocSpy();
3169 ok(hr == S_OK, "got 0x%08x\n", hr);
3170
3171 hr = CoRevokeMallocSpy();
3172 ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr);
3173 }
3174
3175 static void test_CoGetCurrentLogicalThreadId(void)
3176 {
3177 HRESULT hr;
3178 GUID id;
3179
3180 hr = CoGetCurrentLogicalThreadId(NULL);
3181 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3182
3183 id = GUID_NULL;
3184 hr = CoGetCurrentLogicalThreadId(&id);
3185 ok(hr == S_OK, "got 0x%08x\n", hr);
3186 ok(!IsEqualGUID(&id, &GUID_NULL), "got null id\n");
3187 }
3188
3189 static HRESULT WINAPI testinitialize_QI(IInitializeSpy *iface, REFIID riid, void **obj)
3190 {
3191 if (IsEqualIID(riid, &IID_IInitializeSpy) || IsEqualIID(riid, &IID_IUnknown))
3192 {
3193 *obj = iface;
3194 IInitializeSpy_AddRef(iface);
3195 return S_OK;
3196 }
3197
3198 *obj = NULL;
3199 return E_NOINTERFACE;
3200 }
3201
3202 static ULONG WINAPI testinitialize_AddRef(IInitializeSpy *iface)
3203 {
3204 return 2;
3205 }
3206
3207 static ULONG WINAPI testinitialize_Release(IInitializeSpy *iface)
3208 {
3209 return 1;
3210 }
3211
3212 static HRESULT WINAPI testinitialize_PreInitialize(IInitializeSpy *iface, DWORD coinit, DWORD aptrefs)
3213 {
3214 ok(0, "unexpected call\n");
3215 return E_NOTIMPL;
3216 }
3217
3218 static HRESULT WINAPI testinitialize_PostInitialize(IInitializeSpy *iface, HRESULT hr, DWORD coinit, DWORD aptrefs)
3219 {
3220 ok(0, "unexpected call\n");
3221 return E_NOTIMPL;
3222 }
3223
3224 static HRESULT WINAPI testinitialize_PreUninitialize(IInitializeSpy *iface, DWORD aptrefs)
3225 {
3226 ok(0, "unexpected call\n");
3227 return E_NOTIMPL;
3228 }
3229
3230 static HRESULT WINAPI testinitialize_PostUninitialize(IInitializeSpy *iface, DWORD aptrefs)
3231 {
3232 ok(0, "unexpected call\n");
3233 return E_NOTIMPL;
3234 }
3235
3236 static const IInitializeSpyVtbl testinitializevtbl =
3237 {
3238 testinitialize_QI,
3239 testinitialize_AddRef,
3240 testinitialize_Release,
3241 testinitialize_PreInitialize,
3242 testinitialize_PostInitialize,
3243 testinitialize_PreUninitialize,
3244 testinitialize_PostUninitialize
3245 };
3246
3247 static IInitializeSpy testinitialize = { &testinitializevtbl };
3248
3249 static void test_IInitializeSpy(void)
3250 {
3251 ULARGE_INTEGER cookie, cookie1, cookie2;
3252 HRESULT hr;
3253
3254 hr = CoRegisterInitializeSpy(NULL, NULL);
3255 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3256
3257 cookie.QuadPart = 1;
3258 hr = CoRegisterInitializeSpy(NULL, &cookie);
3259 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3260 ok(cookie.QuadPart == 1, "got wrong cookie\n");
3261
3262 hr = CoRegisterInitializeSpy(&testinitialize, NULL);
3263 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3264
3265 cookie.HighPart = 0;
3266 cookie.LowPart = 1;
3267 hr = CoRegisterInitializeSpy(&testinitialize, &cookie);
3268 ok(hr == S_OK, "got 0x%08x\n", hr);
3269 todo_wine {
3270 ok(cookie.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie.HighPart,
3271 GetCurrentThreadId());
3272 ok(cookie.LowPart == 0, "got wrong low part 0x%x\n", cookie.LowPart);
3273 }
3274 /* register same instance one more time */
3275 cookie1.HighPart = 0;
3276 cookie1.LowPart = 0;
3277 hr = CoRegisterInitializeSpy(&testinitialize, &cookie1);
3278 todo_wine {
3279 ok(hr == S_OK, "got 0x%08x\n", hr);
3280 ok(cookie1.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie1.HighPart,
3281 GetCurrentThreadId());
3282 ok(cookie1.LowPart == 1, "got wrong low part 0x%x\n", cookie1.LowPart);
3283 }
3284 cookie2.HighPart = 0;
3285 cookie2.LowPart = 0;
3286 hr = CoRegisterInitializeSpy(&testinitialize, &cookie2);
3287 todo_wine {
3288 ok(hr == S_OK, "got 0x%08x\n", hr);
3289 ok(cookie2.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie2.HighPart,
3290 GetCurrentThreadId());
3291 ok(cookie2.LowPart == 2, "got wrong low part 0x%x\n", cookie2.LowPart);
3292 }
3293 hr = CoRevokeInitializeSpy(cookie1);
3294 todo_wine
3295 ok(hr == S_OK, "got 0x%08x\n", hr);
3296
3297 hr = CoRevokeInitializeSpy(cookie1);
3298 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3299
3300 cookie1.HighPart = 0;
3301 cookie1.LowPart = 0;
3302 hr = CoRegisterInitializeSpy(&testinitialize, &cookie1);
3303 todo_wine {
3304 ok(hr == S_OK, "got 0x%08x\n", hr);
3305 ok(cookie1.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie1.HighPart,
3306 GetCurrentThreadId());
3307 ok(cookie1.LowPart == 1, "got wrong low part 0x%x\n", cookie1.LowPart);
3308 }
3309 hr = CoRevokeInitializeSpy(cookie);
3310 ok(hr == S_OK, "got 0x%08x\n", hr);
3311
3312 hr = CoRevokeInitializeSpy(cookie1);
3313 todo_wine
3314 ok(hr == S_OK, "got 0x%08x\n", hr);
3315
3316 hr = CoRevokeInitializeSpy(cookie2);
3317 todo_wine
3318 ok(hr == S_OK, "got 0x%08x\n", hr);
3319 }
3320
3321 static HRESULT g_persistfile_qi_ret;
3322 static HRESULT g_persistfile_load_ret;
3323 static HRESULT WINAPI testinstance_QI(IPersistFile *iface, REFIID riid, void **obj)
3324 {
3325 if (IsEqualIID(riid, &IID_IUnknown)) {
3326 *obj = iface;
3327 IUnknown_AddRef(iface);
3328 return S_OK;
3329 }
3330
3331 if (IsEqualIID(riid, &IID_IPersistFile)) {
3332 if (SUCCEEDED(g_persistfile_qi_ret)) {
3333 *obj = iface;
3334 IUnknown_AddRef(iface);
3335 }
3336 else
3337 *obj = NULL;
3338 return g_persistfile_qi_ret;
3339 }
3340
3341 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
3342 *obj = NULL;
3343 return E_NOINTERFACE;
3344 }
3345
3346 static ULONG WINAPI testinstance_AddRef(IPersistFile *iface)
3347 {
3348 return 2;
3349 }
3350
3351 static ULONG WINAPI testinstance_Release(IPersistFile *iface)
3352 {
3353 return 1;
3354 }
3355
3356 static HRESULT WINAPI testinstance_GetClassID(IPersistFile *iface, CLSID *clsid)
3357 {
3358 ok(0, "unexpected call\n");
3359 return E_NOTIMPL;
3360 }
3361
3362 static HRESULT WINAPI testinstance_IsDirty(IPersistFile *iface)
3363 {
3364 ok(0, "unexpected call\n");
3365 return E_NOTIMPL;
3366 }
3367
3368 static HRESULT WINAPI testinstance_Load(IPersistFile *iface, LPCOLESTR filename, DWORD mode)
3369 {
3370 return g_persistfile_load_ret;
3371 }
3372
3373 static HRESULT WINAPI testinstance_Save(IPersistFile *iface, LPCOLESTR filename, BOOL remember)
3374 {
3375 return E_NOTIMPL;
3376 }
3377
3378 static HRESULT WINAPI testinstance_SaveCompleted(IPersistFile *iface, LPCOLESTR filename)
3379 {
3380 ok(0, "unexpected call\n");
3381 return E_NOTIMPL;
3382 }
3383
3384 static HRESULT WINAPI testinstance_GetCurFile(IPersistFile *iface, LPOLESTR *filename)
3385 {
3386 ok(0, "unexpected call\n");
3387 return E_NOTIMPL;
3388 }
3389
3390 static const IPersistFileVtbl testpersistfilevtbl = {
3391 testinstance_QI,
3392 testinstance_AddRef,
3393 testinstance_Release,
3394 testinstance_GetClassID,
3395 testinstance_IsDirty,
3396 testinstance_Load,
3397 testinstance_Save,
3398 testinstance_SaveCompleted,
3399 testinstance_GetCurFile
3400 };
3401
3402 static IPersistFile testpersistfile = { &testpersistfilevtbl };
3403
3404 static HRESULT WINAPI getinstance_cf_QI(IClassFactory *iface, REFIID riid, void **obj)
3405 {
3406 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) {
3407 *obj = iface;
3408 IClassFactory_AddRef(iface);
3409 return S_OK;
3410 }
3411
3412 *obj = NULL;
3413 return E_NOINTERFACE;
3414 }
3415
3416 static ULONG WINAPI getinstance_cf_AddRef(IClassFactory *iface)
3417 {
3418 return 2;
3419 }
3420
3421 static ULONG WINAPI getinstance_cf_Release(IClassFactory *iface)
3422 {
3423 return 1;
3424 }
3425
3426 static HRESULT WINAPI getinstance_cf_CreateInstance(IClassFactory *iface, IUnknown *outer,
3427 REFIID riid, void **obj)
3428 {
3429 if (IsEqualIID(riid, &IID_IUnknown)) {
3430 *obj = &testpersistfile;
3431 return S_OK;
3432 }
3433
3434 ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid));
3435 *obj = NULL;
3436 return E_NOTIMPL;
3437 }
3438
3439 static HRESULT WINAPI getinstance_cf_LockServer(IClassFactory *iface, BOOL lock)
3440 {
3441 ok(0, "unexpected call\n");
3442 return E_NOTIMPL;
3443 }
3444
3445 static const IClassFactoryVtbl getinstance_cf_vtbl = {
3446 getinstance_cf_QI,
3447 getinstance_cf_AddRef,
3448 getinstance_cf_Release,
3449 getinstance_cf_CreateInstance,
3450 getinstance_cf_LockServer
3451 };
3452
3453 static IClassFactory getinstance_cf = { &getinstance_cf_vtbl };
3454
3455 static void test_CoGetInstanceFromFile(void)
3456 {
3457 static const WCHAR filenameW[] = {'d','u','m','m','y','p','a','t','h',0};
3458 CLSID *clsid = (CLSID*)&CLSID_testclsid;
3459 MULTI_QI mqi[2];
3460 DWORD cookie;
3461 HRESULT hr;
3462
3463 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3464 ok(hr == S_OK, "got 0x%08x\n", hr);
3465
3466 /* CLSID is not specified, file does not exist */
3467 mqi[0].pIID = &IID_IUnknown;
3468 mqi[0].pItf = NULL;
3469 mqi[0].hr = E_NOTIMPL;
3470 hr = CoGetInstanceFromFile(NULL, NULL, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3471 todo_wine
3472 ok(hr == MK_E_CANTOPENFILE, "got 0x%08x\n", hr);
3473 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3474 ok(mqi[0].hr == E_NOINTERFACE, "got 0x%08x\n", mqi[0].hr);
3475
3476 /* class is not available */
3477 mqi[0].pIID = &IID_IUnknown;
3478 mqi[0].pItf = NULL;
3479 mqi[0].hr = E_NOTIMPL;
3480 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3481 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
3482 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3483 ok(mqi[0].hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", mqi[0].hr);
3484
3485 hr = CoRegisterClassObject(clsid, (IUnknown*)&getinstance_cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE,
3486 &cookie);
3487 ok(hr == S_OK, "got 0x%08x\n", hr);
3488
3489 mqi[0].pIID = &IID_IUnknown;
3490 mqi[0].pItf = (void*)0xdeadbeef;
3491 mqi[0].hr = S_OK;
3492 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3493 todo_wine {
3494 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3495 ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf);
3496 }
3497 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3498
3499 mqi[0].pIID = &IID_IUnknown;
3500 mqi[0].pItf = (void*)0xdeadbeef;
3501 mqi[0].hr = E_NOTIMPL;
3502 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3503 todo_wine {
3504 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3505 ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf);
3506 ok(mqi[0].hr == E_NOTIMPL, "got 0x%08x\n", mqi[0].hr);
3507 }
3508 mqi[0].pIID = &IID_IUnknown;
3509 mqi[0].pItf = NULL;
3510 mqi[0].hr = E_NOTIMPL;
3511 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3512 ok(hr == S_OK, "got 0x%08x\n", hr);
3513 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3514 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3515
3516 mqi[0].pIID = &IID_IUnknown;
3517 mqi[0].pItf = NULL;
3518 mqi[0].hr = S_OK;
3519 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3520 ok(hr == S_OK, "got 0x%08x\n", hr);
3521 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3522 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3523
3524 mqi[0].pIID = &IID_IUnknown;
3525 mqi[0].pItf = NULL;
3526 mqi[0].hr = S_OK;
3527 g_persistfile_qi_ret = S_FALSE;
3528 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3529 ok(hr == S_OK, "got 0x%08x\n", hr);
3530 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3531 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3532 g_persistfile_qi_ret = S_OK;
3533
3534 mqi[0].pIID = &IID_IUnknown;
3535 mqi[0].pItf = NULL;
3536 mqi[0].hr = S_OK;
3537 mqi[1].pIID = &IID_IUnknown;
3538 mqi[1].pItf = NULL;
3539 mqi[1].hr = S_OK;
3540 g_persistfile_qi_ret = 0x8000efef;
3541 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi);
3542 ok(hr == 0x8000efef, "got 0x%08x\n", hr);
3543 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3544 ok(mqi[0].hr == 0x8000efef, "got 0x%08x\n", mqi[0].hr);
3545 ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf);
3546 ok(mqi[1].hr == 0x8000efef, "got 0x%08x\n", mqi[1].hr);
3547 g_persistfile_qi_ret = S_OK;
3548
3549 mqi[0].pIID = &IID_IUnknown;
3550 mqi[0].pItf = NULL;
3551 mqi[0].hr = S_OK;
3552 mqi[1].pIID = &IID_IUnknown;
3553 mqi[1].pItf = NULL;
3554 mqi[1].hr = S_OK;
3555 g_persistfile_load_ret = 0x8000fefe;
3556 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi);
3557 ok(hr == 0x8000fefe, "got 0x%08x\n", hr);
3558 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3559 ok(mqi[0].hr == 0x8000fefe, "got 0x%08x\n", mqi[0].hr);
3560 ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf);
3561 ok(mqi[1].hr == 0x8000fefe, "got 0x%08x\n", mqi[1].hr);
3562 g_persistfile_load_ret = S_OK;
3563
3564 hr = CoRevokeClassObject(cookie);
3565 ok(hr == S_OK, "got 0x%08x\n", hr);
3566
3567 CoUninitialize();
3568 }
3569
3570 static void init_funcs(void)
3571 {
3572 HMODULE hOle32 = GetModuleHandleA("ole32");
3573 HMODULE hAdvapi32 = GetModuleHandleA("advapi32");
3574 HMODULE hkernel32 = GetModuleHandleA("kernel32");
3575
3576 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
3577 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
3578 pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
3579 pCoTreatAsClass = (void*)GetProcAddress(hOle32,"CoTreatAsClass");
3580 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
3581 pCoGetApartmentType = (void*)GetProcAddress(hOle32, "CoGetApartmentType");
3582 pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA");
3583 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
3584 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
3585
3586 pActivateActCtx = (void*)GetProcAddress(hkernel32, "ActivateActCtx");
3587 pCreateActCtxW = (void*)GetProcAddress(hkernel32, "CreateActCtxW");
3588 pDeactivateActCtx = (void*)GetProcAddress(hkernel32, "DeactivateActCtx");
3589 pIsWow64Process = (void*)GetProcAddress(hkernel32, "IsWow64Process");
3590 pReleaseActCtx = (void*)GetProcAddress(hkernel32, "ReleaseActCtx");
3591 }
3592
3593 START_TEST(compobj)
3594 {
3595 init_funcs();
3596
3597 if (!pCoInitializeEx)
3598 {
3599 trace("You need DCOM95 installed to run this test\n");
3600 return;
3601 }
3602
3603 if (!pCreateActCtxW)
3604 win_skip("Activation contexts are not supported, some tests will be skipped.\n");
3605
3606 test_ProgIDFromCLSID();
3607 test_CLSIDFromProgID();
3608 test_CLSIDFromString();
3609 test_IIDFromString();
3610 test_StringFromGUID2();
3611 test_CoCreateInstance();
3612 test_ole_menu();
3613 test_CoGetClassObject();
3614 test_CoCreateInstanceEx();
3615 test_CoRegisterMessageFilter();
3616 test_CoRegisterPSClsid();
3617 test_CoGetPSClsid();
3618 test_CoUnmarshalInterface();
3619 test_CoGetInterfaceAndReleaseStream();
3620 test_CoMarshalInterface();
3621 test_CoMarshalInterThreadInterfaceInStream();
3622 test_CoRegisterClassObject();
3623 test_registered_object_thread_affinity();
3624 test_CoFreeUnusedLibraries();
3625 test_CoGetObjectContext();
3626 test_CoGetCallContext();
3627 test_CoGetContextToken();
3628 test_TreatAsClass();
3629 test_CoInitializeEx();
3630 test_OleInitialize_InitCounting();
3631 test_OleRegGetMiscStatus();
3632 test_CoCreateGuid();
3633 test_CoWaitForMultipleHandles();
3634 test_CoGetMalloc();
3635 test_OleRegGetUserType();
3636 test_CoGetApartmentType();
3637 test_IMallocSpy();
3638 test_CoGetCurrentLogicalThreadId();
3639 test_IInitializeSpy();
3640 test_CoGetInstanceFromFile();
3641 }