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