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