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