vbscript: Moved Error object implementation to global.c.
[wine/multimedia.git] / dlls / ole32 / tests / compobj.c
blobb85842bcae076ed7dc5ed85e7bfa4d82dbb29b9d
1 /*
2 * Component Object Tests
4 * Copyright 2005 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #define CONST_VTABLE
24 #include <stdarg.h>
25 #include <stdio.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #define USE_COM_CONTEXT_DEF
30 #include "initguid.h"
31 #include "objbase.h"
32 #include "shlguid.h"
33 #include "urlmon.h" /* for CLSID_FileProtocol */
35 #include "ctxtcall.h"
37 #include "wine/test.h"
39 /* functions that are not present on all versions of Windows */
40 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
41 static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
42 static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
43 static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
44 static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
45 static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
47 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
48 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
49 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
50 static void (WINAPI *pReleaseActCtx)(HANDLE);
52 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
53 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
54 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
56 static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
57 static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
58 static const GUID IID_Testiface = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
59 static const GUID IID_Testiface2 = { 0x32222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
60 static const GUID IID_Testiface3 = { 0x42222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
61 static const GUID IID_Testiface4 = { 0x52222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
62 static const GUID IID_Testiface5 = { 0x62222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
63 static const GUID IID_Testiface6 = { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
64 static const GUID IID_TestPS = { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } };
66 DEFINE_GUID(CLSID_InProcFreeMarshaler, 0x0000033a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
68 static const WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
69 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
70 static const WCHAR wszCLSID_StdFont[] =
72 '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
73 '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
75 static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
76 static const WCHAR cf_brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
77 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0};
79 DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
80 DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
82 static LONG cLocks;
84 static void LockModule(void)
86 InterlockedIncrement(&cLocks);
89 static void UnlockModule(void)
91 InterlockedDecrement(&cLocks);
94 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
95 LPCLASSFACTORY iface,
96 REFIID riid,
97 LPVOID *ppvObj)
99 if (ppvObj == NULL) return E_POINTER;
101 if (IsEqualGUID(riid, &IID_IUnknown) ||
102 IsEqualGUID(riid, &IID_IClassFactory))
104 *ppvObj = iface;
105 IClassFactory_AddRef(iface);
106 return S_OK;
109 *ppvObj = NULL;
110 return E_NOINTERFACE;
113 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
115 LockModule();
116 return 2; /* non-heap-based object */
119 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
121 UnlockModule();
122 return 1; /* non-heap-based object */
125 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
126 LPCLASSFACTORY iface,
127 IUnknown *pUnkOuter,
128 REFIID riid,
129 LPVOID *ppvObj)
131 *ppvObj = NULL;
132 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
133 return E_NOINTERFACE;
136 static HRESULT WINAPI Test_IClassFactory_LockServer(
137 LPCLASSFACTORY iface,
138 BOOL fLock)
140 return S_OK;
143 static const IClassFactoryVtbl TestClassFactory_Vtbl =
145 Test_IClassFactory_QueryInterface,
146 Test_IClassFactory_AddRef,
147 Test_IClassFactory_Release,
148 Test_IClassFactory_CreateInstance,
149 Test_IClassFactory_LockServer
152 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
154 static WCHAR manifest_path[MAX_PATH];
156 static BOOL create_manifest_file(const char *filename, const char *manifest)
158 int manifest_len;
159 DWORD size;
160 HANDLE file;
161 WCHAR path[MAX_PATH];
163 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
164 GetFullPathNameW(path, sizeof(manifest_path)/sizeof(WCHAR), manifest_path, NULL);
166 manifest_len = strlen(manifest);
167 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
168 FILE_ATTRIBUTE_NORMAL, NULL);
169 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
170 if(file == INVALID_HANDLE_VALUE)
171 return FALSE;
172 WriteFile(file, manifest, manifest_len, &size, NULL);
173 CloseHandle(file);
175 return TRUE;
178 static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie)
180 WCHAR path[MAX_PATH];
181 ACTCTXW actctx;
182 HANDLE handle;
183 BOOL ret;
185 if (!pCreateActCtxW) return NULL;
187 create_manifest_file("file.manifest", manifest);
189 MultiByteToWideChar( CP_ACP, 0, "file.manifest", -1, path, MAX_PATH );
190 memset(&actctx, 0, sizeof(ACTCTXW));
191 actctx.cbSize = sizeof(ACTCTXW);
192 actctx.lpSource = path;
194 handle = pCreateActCtxW(&actctx);
195 ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* some old XP/2k3 versions */,
196 "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
197 if (handle == INVALID_HANDLE_VALUE)
199 win_skip("activation context generation failed, some tests will be skipped\n");
200 handle = NULL;
203 ok(actctx.cbSize == sizeof(ACTCTXW), "actctx.cbSize=%d\n", actctx.cbSize);
204 ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
205 ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
206 ok(actctx.wProcessorArchitecture == 0, "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
207 ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId);
208 ok(actctx.lpAssemblyDirectory == NULL, "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
209 ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
210 ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n", actctx.lpApplicationName);
211 ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
213 DeleteFileA("file.manifest");
215 if (handle)
217 ret = pActivateActCtx(handle, cookie);
218 ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
221 return handle;
224 static const char actctx_manifest[] =
225 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
226 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
227 " publicKeyToken=\"6595b6414666f1df\" />"
228 "<file name=\"testlib.dll\">"
229 " <comClass"
230 " clsid=\"{0000033a-0000-0000-c000-000000000046}\""
231 " progid=\"FTMarshal\""
232 " />"
233 " <comClass"
234 " clsid=\"{5201163f-8164-4fd0-a1a2-5d5a3654d3bd}\""
235 " progid=\"WineOOPTest\""
236 " />"
237 " <comClass description=\"Test com class\""
238 " clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
239 " progid=\"ProgId.ProgId\""
240 " miscStatusIcon=\"recomposeonresize\""
241 " />"
242 " <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb851}\""
243 " progid=\"CustomFont\""
244 " miscStatusIcon=\"recomposeonresize\""
245 " miscStatusContent=\"insideout\""
246 " />"
247 " <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
248 " progid=\"StdFont\""
249 " />"
250 " <comClass clsid=\"{62222222-1234-1234-1234-56789abcdef0}\" >"
251 " <progid>ProgId.ProgId.1</progid>"
252 " </comClass>"
253 " <comInterfaceProxyStub "
254 " name=\"Iifaceps\""
255 " iid=\"{22222222-1234-1234-1234-56789abcdef0}\""
256 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
257 " />"
258 "</file>"
259 " <comInterfaceExternalProxyStub "
260 " name=\"Iifaceps2\""
261 " iid=\"{32222222-1234-1234-1234-56789abcdef0}\""
262 " />"
263 " <comInterfaceExternalProxyStub "
264 " name=\"Iifaceps3\""
265 " iid=\"{42222222-1234-1234-1234-56789abcdef0}\""
266 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
267 " />"
268 " <comInterfaceExternalProxyStub "
269 " name=\"Iifaceps4\""
270 " iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
271 " proxyStubClsid32=\"{00000000-0000-0000-0000-000000000000}\""
272 " />"
273 " <clrClass "
274 " clsid=\"{72222222-1234-1234-1234-56789abcdef0}\""
275 " name=\"clrclass\""
276 " >"
277 " <progid>clrprogid.1</progid>"
278 " </clrClass>"
279 "</assembly>";
281 DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
283 static void test_ProgIDFromCLSID(void)
285 ULONG_PTR cookie = 0;
286 LPWSTR progid;
287 HANDLE handle;
288 HRESULT hr;
290 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
291 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
292 if (hr == S_OK)
294 ok(!lstrcmpiW(progid, stdfont), "Didn't get expected prog ID\n");
295 CoTaskMemFree(progid);
298 progid = (LPWSTR)0xdeadbeef;
299 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
300 ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
301 ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
303 hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
304 ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
306 if ((handle = activate_context(actctx_manifest, &cookie)))
308 static const WCHAR customfontW[] = {'C','u','s','t','o','m','F','o','n','t',0};
310 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
311 ok(hr == S_OK, "got 0x%08x\n", hr);
312 ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid));
313 CoTaskMemFree(progid);
315 /* try something registered and redirected */
316 progid = NULL;
317 hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
318 ok(hr == S_OK, "got 0x%08x\n", hr);
319 ok(!lstrcmpiW(progid, customfontW), "got wrong progid %s\n", wine_dbgstr_w(progid));
320 CoTaskMemFree(progid);
322 /* classes without default progid, progid list is not used */
323 hr = ProgIDFromCLSID(&IID_Testiface5, &progid);
324 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
326 hr = ProgIDFromCLSID(&IID_Testiface6, &progid);
327 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
329 pDeactivateActCtx(0, cookie);
330 pReleaseActCtx(handle);
334 static void test_CLSIDFromProgID(void)
336 ULONG_PTR cookie = 0;
337 HANDLE handle;
338 CLSID clsid;
339 HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
340 ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
341 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
343 hr = CLSIDFromString(stdfont, &clsid);
344 ok_ole_success(hr, "CLSIDFromString");
345 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
347 /* test some failure cases */
349 hr = CLSIDFromProgID(wszNonExistent, NULL);
350 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
352 hr = CLSIDFromProgID(NULL, &clsid);
353 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
355 memset(&clsid, 0xcc, sizeof(clsid));
356 hr = CLSIDFromProgID(wszNonExistent, &clsid);
357 ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
358 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
360 /* fails without proper context */
361 memset(&clsid, 0xcc, sizeof(clsid));
362 hr = CLSIDFromProgID(progidW, &clsid);
363 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
364 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "wrong clsid\n");
366 if ((handle = activate_context(actctx_manifest, &cookie)))
368 GUID clsid1;
370 memset(&clsid, 0xcc, sizeof(clsid));
371 hr = CLSIDFromProgID(wszNonExistent, &clsid);
372 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
373 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "should have zero CLSID on failure\n");
375 /* CLSIDFromString() doesn't check activation context */
376 hr = CLSIDFromString(progidW, &clsid);
377 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
379 clsid = CLSID_NULL;
380 hr = CLSIDFromProgID(progidW, &clsid);
381 /* it returns generated CLSID here */
382 ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL),
383 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid));
385 /* duplicate progid present in context - returns generated guid here too */
386 clsid = CLSID_NULL;
387 hr = CLSIDFromProgID(stdfont, &clsid);
388 ok(hr == S_OK, "got 0x%08x\n", hr);
389 clsid1 = CLSID_StdFont;
390 /* that's where it differs from StdFont */
391 clsid1.Data4[7] = 0x52;
392 ok(!IsEqualCLSID(&clsid, &CLSID_StdFont) && !IsEqualCLSID(&clsid, &CLSID_NULL) && !IsEqualCLSID(&clsid, &clsid1),
393 "got %s\n", wine_dbgstr_guid(&clsid));
395 pDeactivateActCtx(0, cookie);
396 pReleaseActCtx(handle);
400 static void test_CLSIDFromString(void)
402 CLSID clsid;
403 WCHAR wszCLSID_Broken[50];
404 UINT i;
406 HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
407 ok_ole_success(hr, "CLSIDFromString");
408 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
410 memset(&clsid, 0xab, sizeof(clsid));
411 hr = CLSIDFromString(NULL, &clsid);
412 ok(hr == S_OK, "got 0x%08x\n", hr);
413 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
415 /* string is longer, but starts with a valid CLSID */
416 memset(&clsid, 0, sizeof(clsid));
417 hr = CLSIDFromString(cf_brokenW, &clsid);
418 ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
419 ok(IsEqualCLSID(&clsid, &IID_IClassFactory), "got %s\n", wine_dbgstr_guid(&clsid));
421 lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
422 for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
423 wszCLSID_Broken[i] = 'A';
424 wszCLSID_Broken[i] = '\0';
426 memset(&clsid, 0, sizeof(CLSID));
427 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
428 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
429 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
431 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
432 memset(&clsid, 0, sizeof(CLSID));
433 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
434 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
435 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
437 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
438 memset(&clsid, 0, sizeof(CLSID));
439 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
440 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
441 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
443 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
444 memset(&clsid, 0, sizeof(CLSID));
445 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
446 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
447 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
449 memset(&clsid, 0xcc, sizeof(CLSID));
450 hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
451 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
452 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
454 wszCLSID_Broken[9] = '*';
455 memset(&clsid, 0xcc, sizeof(CLSID));
456 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
457 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
458 ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
459 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
461 wszCLSID_Broken[3] = '*';
462 memset(&clsid, 0xcc, sizeof(CLSID));
463 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
464 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
465 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
466 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
468 wszCLSID_Broken[3] = '\0';
469 memset(&clsid, 0xcc, sizeof(CLSID));
470 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
471 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
472 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
473 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
476 static void test_IIDFromString(void)
478 static const WCHAR cfW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
479 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
480 static const WCHAR brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
481 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
482 static const WCHAR broken2W[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
483 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
484 static const WCHAR broken3W[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
485 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
486 HRESULT hr;
487 IID iid;
489 hr = IIDFromString(wszCLSID_StdFont, &iid);
490 ok(hr == S_OK, "got 0x%08x\n", hr);
491 ok(IsEqualIID(&iid, &CLSID_StdFont), "got iid %s\n", wine_dbgstr_guid(&iid));
493 memset(&iid, 0xab, sizeof(iid));
494 hr = IIDFromString(NULL, &iid);
495 ok(hr == S_OK, "got 0x%08x\n", hr);
496 ok(IsEqualIID(&iid, &CLSID_NULL), "got iid %s\n", wine_dbgstr_guid(&iid));
498 hr = IIDFromString(cfW, &iid);
499 ok(hr == S_OK, "got 0x%08x\n", hr);
500 ok(IsEqualIID(&iid, &IID_IClassFactory), "got iid %s\n", wine_dbgstr_guid(&iid));
502 /* string starts with a valid IID but is longer */
503 memset(&iid, 0xab, sizeof(iid));
504 hr = IIDFromString(cf_brokenW, &iid);
505 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
506 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
508 /* invalid IID in a valid format */
509 memset(&iid, 0xab, sizeof(iid));
510 hr = IIDFromString(brokenW, &iid);
511 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
512 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
514 memset(&iid, 0xab, sizeof(iid));
515 hr = IIDFromString(broken2W, &iid);
516 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
517 ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
519 /* format is broken, but string length is okay */
520 memset(&iid, 0xab, sizeof(iid));
521 hr = IIDFromString(broken3W, &iid);
522 ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
523 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
525 /* invalid string */
526 memset(&iid, 0xab, sizeof(iid));
527 hr = IIDFromString(wszNonExistent, &iid);
528 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
529 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
531 /* valid ProgID */
532 memset(&iid, 0xab, sizeof(iid));
533 hr = IIDFromString(stdfont, &iid);
534 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
535 ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
538 static void test_StringFromGUID2(void)
540 WCHAR str[50];
541 int len;
543 /* invalid pointer */
544 SetLastError(0xdeadbeef);
545 len = StringFromGUID2(NULL,str,50);
546 ok(len == 0, "len: %d (expected 0)\n", len);
547 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
549 /* Test corner cases for buffer size */
550 len = StringFromGUID2(&CLSID_StdFont,str,50);
551 ok(len == 39, "len: %d (expected 39)\n", len);
552 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
554 memset(str,0,sizeof str);
555 len = StringFromGUID2(&CLSID_StdFont,str,39);
556 ok(len == 39, "len: %d (expected 39)\n", len);
557 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
559 len = StringFromGUID2(&CLSID_StdFont,str,38);
560 ok(len == 0, "len: %d (expected 0)\n", len);
562 len = StringFromGUID2(&CLSID_StdFont,str,30);
563 ok(len == 0, "len: %d (expected 0)\n", len);
566 struct info
568 HANDLE wait, stop;
571 static DWORD CALLBACK ole_initialize_thread(LPVOID pv)
573 HRESULT hr;
574 struct info *info = pv;
576 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
578 SetEvent(info->wait);
579 WaitForSingleObject(info->stop, 10000);
581 CoUninitialize();
582 return hr;
585 static void test_CoCreateInstance(void)
587 HRESULT hr;
588 HANDLE thread;
589 DWORD tid, exitcode;
590 IUnknown *pUnk;
591 struct info info;
592 REFCLSID rclsid = &CLSID_InternetZoneManager;
594 pUnk = (IUnknown *)0xdeadbeef;
595 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
596 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
597 ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
599 OleInitialize(NULL);
601 /* test errors returned for non-registered clsids */
602 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
603 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
604 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pUnk);
605 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
606 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (void **)&pUnk);
607 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
608 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_REMOTE_SERVER, &IID_IUnknown, (void **)&pUnk);
609 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
611 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
612 if(hr == REGDB_E_CLASSNOTREG)
614 skip("IE not installed so can't test CoCreateInstance\n");
615 OleUninitialize();
616 return;
619 ok_ole_success(hr, "CoCreateInstance");
620 if(pUnk) IUnknown_Release(pUnk);
621 OleUninitialize();
623 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
624 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
626 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
627 thread has already done so */
629 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
630 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
632 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
633 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
635 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
636 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
638 ok( !WaitForSingleObject(info.wait, 10000 ), "wait timed out\n" );
640 pUnk = (IUnknown *)0xdeadbeef;
641 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
642 ok(hr == S_OK, "CoCreateInstance should have returned S_OK instead of 0x%08x\n", hr);
643 if (pUnk) IUnknown_Release(pUnk);
645 SetEvent(info.stop);
646 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
648 GetExitCodeThread(thread, &exitcode);
649 hr = exitcode;
650 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
652 CloseHandle(thread);
653 CloseHandle(info.wait);
654 CloseHandle(info.stop);
657 static void test_CoGetClassObject(void)
659 HRESULT hr;
660 HANDLE thread, handle;
661 DWORD tid, exitcode;
662 ULONG_PTR cookie;
663 IUnknown *pUnk;
664 struct info info;
665 REFCLSID rclsid = &CLSID_InternetZoneManager;
666 HKEY hkey;
667 LONG res;
669 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
670 ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
671 ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
673 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
674 ok(hr == E_INVALIDARG ||
675 broken(hr == CO_E_NOTINITIALIZED), /* win9x */
676 "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
678 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
679 thread has already done so */
681 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
682 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
684 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
685 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
687 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
688 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
690 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
692 pUnk = (IUnknown *)0xdeadbeef;
693 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
694 if(hr == REGDB_E_CLASSNOTREG)
695 skip("IE not installed so can't test CoGetClassObject\n");
696 else
698 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
699 if (pUnk) IUnknown_Release(pUnk);
702 SetEvent(info.stop);
703 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
705 GetExitCodeThread(thread, &exitcode);
706 hr = exitcode;
707 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
709 CloseHandle(thread);
710 CloseHandle(info.wait);
711 CloseHandle(info.stop);
713 if (!pRegOverridePredefKey)
715 win_skip("RegOverridePredefKey not available\n");
716 return;
719 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
721 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
722 if (hr == S_OK)
724 IUnknown_Release(pUnk);
726 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
727 KEY_ALL_ACCESS, NULL, &hkey, NULL);
728 ok(!res, "RegCreateKeyEx returned %d\n", res);
730 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
731 ok(!res, "RegOverridePredefKey returned %d\n", res);
733 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
734 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
736 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
737 ok(!res, "RegOverridePredefKey returned %d\n", res);
739 if (hr == S_OK) IUnknown_Release(pUnk);
740 RegCloseKey(hkey);
743 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
744 ok(hr == S_OK, "got 0x%08x\n", hr);
745 IUnknown_Release(pUnk);
747 /* context redefines FreeMarshaler CLSID */
748 if ((handle = activate_context(actctx_manifest, &cookie)))
750 hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
751 ok(hr == S_OK, "got 0x%08x\n", hr);
752 IUnknown_Release(pUnk);
754 pDeactivateActCtx(0, cookie);
755 pReleaseActCtx(handle);
758 CoUninitialize();
761 static ATOM register_dummy_class(void)
763 WNDCLASSA wc =
766 DefWindowProcA,
769 GetModuleHandleA(NULL),
770 NULL,
771 LoadCursorA(NULL, (LPSTR)IDC_ARROW),
772 (HBRUSH)(COLOR_BTNFACE+1),
773 NULL,
774 "WineOleTestClass",
777 return RegisterClassA(&wc);
780 static void test_ole_menu(void)
782 HWND hwndFrame;
783 HRESULT hr;
785 hwndFrame = CreateWindowA((LPCSTR)MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
786 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
787 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
789 DestroyWindow(hwndFrame);
793 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
795 if (ppvObj == NULL) return E_POINTER;
797 if (IsEqualGUID(riid, &IID_IUnknown) ||
798 IsEqualGUID(riid, &IID_IClassFactory))
800 *ppvObj = iface;
801 IMessageFilter_AddRef(iface);
802 return S_OK;
805 return E_NOINTERFACE;
808 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
810 return 2; /* non-heap object */
813 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
815 return 1; /* non-heap object */
818 static DWORD WINAPI MessageFilter_HandleInComingCall(
819 IMessageFilter *iface,
820 DWORD dwCallType,
821 HTASK threadIDCaller,
822 DWORD dwTickCount,
823 LPINTERFACEINFO lpInterfaceInfo)
825 trace("HandleInComingCall\n");
826 return SERVERCALL_ISHANDLED;
829 static DWORD WINAPI MessageFilter_RetryRejectedCall(
830 IMessageFilter *iface,
831 HTASK threadIDCallee,
832 DWORD dwTickCount,
833 DWORD dwRejectType)
835 trace("RetryRejectedCall\n");
836 return 0;
839 static DWORD WINAPI MessageFilter_MessagePending(
840 IMessageFilter *iface,
841 HTASK threadIDCallee,
842 DWORD dwTickCount,
843 DWORD dwPendingType)
845 trace("MessagePending\n");
846 return PENDINGMSG_WAITNOPROCESS;
849 static const IMessageFilterVtbl MessageFilter_Vtbl =
851 MessageFilter_QueryInterface,
852 MessageFilter_AddRef,
853 MessageFilter_Release,
854 MessageFilter_HandleInComingCall,
855 MessageFilter_RetryRejectedCall,
856 MessageFilter_MessagePending
859 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
861 static void test_CoRegisterMessageFilter(void)
863 HRESULT hr;
864 IMessageFilter *prev_filter;
866 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
867 ok(hr == CO_E_NOT_SUPPORTED,
868 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
869 hr);
871 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
872 prev_filter = (IMessageFilter *)0xdeadbeef;
873 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
874 ok(hr == CO_E_NOT_SUPPORTED,
875 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
876 hr);
877 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
878 "prev_filter should have been set to %p\n", prev_filter);
879 CoUninitialize();
881 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
883 hr = CoRegisterMessageFilter(NULL, NULL);
884 ok_ole_success(hr, "CoRegisterMessageFilter");
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);
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);
895 hr = CoRegisterMessageFilter(NULL, NULL);
896 ok_ole_success(hr, "CoRegisterMessageFilter");
898 CoUninitialize();
901 static HRESULT WINAPI Test_IUnknown_QueryInterface(
902 IUnknown *iface,
903 REFIID riid,
904 LPVOID *ppvObj)
906 if (ppvObj == NULL) return E_POINTER;
908 if (IsEqualIID(riid, &IID_IUnknown) ||
909 IsEqualIID(riid, &IID_IWineTest))
911 *ppvObj = iface;
912 IUnknown_AddRef(iface);
913 return S_OK;
916 *ppvObj = NULL;
917 return E_NOINTERFACE;
920 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
922 return 2; /* non-heap-based object */
925 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
927 return 1; /* non-heap-based object */
930 static const IUnknownVtbl TestUnknown_Vtbl =
932 Test_IUnknown_QueryInterface,
933 Test_IUnknown_AddRef,
934 Test_IUnknown_Release,
937 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
939 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
940 IPSFactoryBuffer * This,
941 /* [in] */ REFIID riid,
942 /* [iid_is][out] */ void **ppvObject)
944 if (IsEqualIID(riid, &IID_IUnknown) ||
945 IsEqualIID(riid, &IID_IPSFactoryBuffer))
947 *ppvObject = This;
948 IPSFactoryBuffer_AddRef(This);
949 return S_OK;
951 return E_NOINTERFACE;
954 static ULONG WINAPI PSFactoryBuffer_AddRef(
955 IPSFactoryBuffer * This)
957 return 2;
960 static ULONG WINAPI PSFactoryBuffer_Release(
961 IPSFactoryBuffer * This)
963 return 1;
966 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
967 IPSFactoryBuffer * This,
968 /* [in] */ IUnknown *pUnkOuter,
969 /* [in] */ REFIID riid,
970 /* [out] */ IRpcProxyBuffer **ppProxy,
971 /* [out] */ void **ppv)
973 return E_NOTIMPL;
976 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
977 IPSFactoryBuffer * This,
978 /* [in] */ REFIID riid,
979 /* [unique][in] */ IUnknown *pUnkServer,
980 /* [out] */ IRpcStubBuffer **ppStub)
982 return E_NOTIMPL;
985 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
987 PSFactoryBuffer_QueryInterface,
988 PSFactoryBuffer_AddRef,
989 PSFactoryBuffer_Release,
990 PSFactoryBuffer_CreateProxy,
991 PSFactoryBuffer_CreateStub
994 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
996 static const CLSID CLSID_WineTestPSFactoryBuffer =
998 0x52011640,
999 0x8164,
1000 0x4fd0,
1001 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1002 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
1004 static void test_CoRegisterPSClsid(void)
1006 HRESULT hr;
1007 DWORD dwRegistrationKey;
1008 IStream *stream;
1009 CLSID clsid;
1011 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1012 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1014 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1016 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
1017 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
1018 ok_ole_success(hr, "CoRegisterClassObject");
1020 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1021 ok_ole_success(hr, "CoRegisterPSClsid");
1023 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1024 ok_ole_success(hr, "CreateStreamOnHGlobal");
1026 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1027 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1028 IStream_Release(stream);
1030 hr = CoRevokeClassObject(dwRegistrationKey);
1031 ok_ole_success(hr, "CoRevokeClassObject");
1033 CoUninitialize();
1035 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1037 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1038 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
1040 CoUninitialize();
1043 static void test_CoGetPSClsid(void)
1045 ULONG_PTR cookie;
1046 HANDLE handle;
1047 HRESULT hr;
1048 CLSID clsid;
1049 HKEY hkey;
1050 LONG res;
1052 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1053 ok(hr == CO_E_NOTINITIALIZED,
1054 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
1055 hr);
1057 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1059 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1060 ok_ole_success(hr, "CoGetPSClsid");
1062 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1063 ok(hr == REGDB_E_IIDNOTREG,
1064 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
1065 hr);
1067 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
1068 ok(hr == E_INVALIDARG,
1069 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
1070 hr);
1072 if (!pRegOverridePredefKey)
1074 win_skip("RegOverridePredefKey not available\n");
1075 CoUninitialize();
1076 return;
1078 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1079 ok_ole_success(hr, "CoGetPSClsid");
1081 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
1082 KEY_ALL_ACCESS, NULL, &hkey, NULL);
1083 ok(!res, "RegCreateKeyEx returned %d\n", res);
1085 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
1086 ok(!res, "RegOverridePredefKey returned %d\n", res);
1088 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1089 ok_ole_success(hr, "CoGetPSClsid");
1091 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
1092 ok(!res, "RegOverridePredefKey returned %d\n", res);
1094 RegCloseKey(hkey);
1096 /* not registered CLSID */
1097 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1098 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1100 if ((handle = activate_context(actctx_manifest, &cookie)))
1102 memset(&clsid, 0, sizeof(clsid));
1103 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1104 ok(hr == S_OK, "got 0x%08x\n", hr);
1105 ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1107 memset(&clsid, 0, sizeof(clsid));
1108 hr = CoGetPSClsid(&IID_Testiface2, &clsid);
1109 ok(hr == S_OK, "got 0x%08x\n", hr);
1110 ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1112 memset(&clsid, 0, sizeof(clsid));
1113 hr = CoGetPSClsid(&IID_Testiface3, &clsid);
1114 ok(hr == S_OK, "got 0x%08x\n", hr);
1115 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1117 memset(&clsid, 0xaa, sizeof(clsid));
1118 hr = CoGetPSClsid(&IID_Testiface4, &clsid);
1119 ok(hr == S_OK, "got 0x%08x\n", hr);
1120 ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1122 /* register same interface and try to get CLSID back */
1123 hr = CoRegisterPSClsid(&IID_Testiface, &IID_Testiface4);
1124 ok(hr == S_OK, "got 0x%08x\n", hr);
1125 memset(&clsid, 0, sizeof(clsid));
1126 hr = CoGetPSClsid(&IID_Testiface, &clsid);
1127 ok(hr == S_OK, "got 0x%08x\n", hr);
1128 ok(IsEqualGUID(&clsid, &IID_Testiface4), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1130 pDeactivateActCtx(0, cookie);
1131 pReleaseActCtx(handle);
1134 CoUninitialize();
1137 /* basic test, mainly for invalid arguments. see marshal.c for more */
1138 static void test_CoUnmarshalInterface(void)
1140 IUnknown *pProxy;
1141 IStream *pStream;
1142 HRESULT hr;
1144 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
1145 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1147 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1148 ok_ole_success(hr, "CreateStreamOnHGlobal");
1150 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1151 todo_wine
1152 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1154 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1156 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1157 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1159 CoUninitialize();
1161 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
1162 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1164 IStream_Release(pStream);
1167 static void test_CoGetInterfaceAndReleaseStream(void)
1169 HRESULT hr;
1170 IUnknown *pUnk;
1172 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1174 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
1175 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
1177 CoUninitialize();
1180 /* basic test, mainly for invalid arguments. see marshal.c for more */
1181 static void test_CoMarshalInterface(void)
1183 IStream *pStream;
1184 HRESULT hr;
1185 static const LARGE_INTEGER llZero;
1187 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1189 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1190 ok_ole_success(hr, "CreateStreamOnHGlobal");
1192 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1193 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1195 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1196 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1198 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1199 ok_ole_success(hr, "CoMarshalInterface");
1201 /* stream not rewound */
1202 hr = CoReleaseMarshalData(pStream);
1203 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1205 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1206 ok_ole_success(hr, "IStream_Seek");
1208 hr = CoReleaseMarshalData(pStream);
1209 ok_ole_success(hr, "CoReleaseMarshalData");
1211 IStream_Release(pStream);
1213 CoUninitialize();
1216 static void test_CoMarshalInterThreadInterfaceInStream(void)
1218 IStream *pStream;
1219 HRESULT hr;
1220 IClassFactory *pProxy;
1222 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1224 cLocks = 0;
1226 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
1227 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1229 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
1230 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1232 ok_no_locks();
1234 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
1235 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
1237 ok_more_than_one_lock();
1239 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1240 ok_ole_success(hr, "CoUnmarshalInterface");
1242 IClassFactory_Release(pProxy);
1243 IStream_Release(pStream);
1245 ok_no_locks();
1247 CoUninitialize();
1250 static void test_CoRegisterClassObject(void)
1252 ULONG_PTR ctxcookie;
1253 HANDLE handle;
1254 DWORD cookie;
1255 HRESULT hr;
1256 IClassFactory *pcf;
1258 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1260 /* CLSCTX_INPROC_SERVER */
1261 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1262 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1263 ok_ole_success(hr, "CoRegisterClassObject");
1264 hr = CoRevokeClassObject(cookie);
1265 ok_ole_success(hr, "CoRevokeClassObject");
1267 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1268 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1269 ok_ole_success(hr, "CoRegisterClassObject");
1270 hr = CoRevokeClassObject(cookie);
1271 ok_ole_success(hr, "CoRevokeClassObject");
1273 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1274 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1275 ok_ole_success(hr, "CoRegisterClassObject");
1276 hr = CoRevokeClassObject(cookie);
1277 ok_ole_success(hr, "CoRevokeClassObject");
1279 /* CLSCTX_LOCAL_SERVER */
1280 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1281 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1282 ok_ole_success(hr, "CoRegisterClassObject");
1283 hr = CoRevokeClassObject(cookie);
1284 ok_ole_success(hr, "CoRevokeClassObject");
1286 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1287 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1288 ok_ole_success(hr, "CoRegisterClassObject");
1289 hr = CoRevokeClassObject(cookie);
1290 ok_ole_success(hr, "CoRevokeClassObject");
1292 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1293 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1294 ok_ole_success(hr, "CoRegisterClassObject");
1295 hr = CoRevokeClassObject(cookie);
1296 ok_ole_success(hr, "CoRevokeClassObject");
1298 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
1299 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1300 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1301 ok_ole_success(hr, "CoRegisterClassObject");
1302 hr = CoRevokeClassObject(cookie);
1303 ok_ole_success(hr, "CoRevokeClassObject");
1305 /* test whether an object that doesn't support IClassFactory can be
1306 * registered for CLSCTX_LOCAL_SERVER */
1307 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
1308 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1309 ok_ole_success(hr, "CoRegisterClassObject");
1310 hr = CoRevokeClassObject(cookie);
1311 ok_ole_success(hr, "CoRevokeClassObject");
1313 /* test whether registered class becomes invalid when apartment is destroyed */
1314 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1315 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1316 ok_ole_success(hr, "CoRegisterClassObject");
1318 CoUninitialize();
1319 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1321 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
1322 &IID_IClassFactory, (void **)&pcf);
1323 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
1325 /* crashes with at least win9x DCOM! */
1326 if (0)
1327 CoRevokeClassObject(cookie);
1329 /* test that object is accessible */
1330 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER,
1331 REGCLS_MULTIPLEUSE, &cookie);
1332 ok(hr == S_OK, "got 0x%08x\n", hr);
1334 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1335 ok(hr == S_OK, "got 0x%08x\n", hr);
1336 IClassFactory_Release(pcf);
1338 /* context now contains CLSID_WineOOPTest, test if registered one could still be used */
1339 if ((handle = activate_context(actctx_manifest, &ctxcookie)))
1341 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1342 todo_wine
1343 ok(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), "got 0x%08x\n", hr);
1345 pDeactivateActCtx(0, ctxcookie);
1346 pReleaseActCtx(handle);
1349 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1350 ok(hr == S_OK, "got 0x%08x\n", hr);
1351 IClassFactory_Release(pcf);
1353 hr = CoRevokeClassObject(cookie);
1354 ok(hr == S_OK, "got 0x%08x\n", hr);
1356 CoUninitialize();
1359 static HRESULT get_class_object(CLSCTX clsctx)
1361 HRESULT hr;
1362 IClassFactory *pcf;
1364 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1365 (void **)&pcf);
1367 if (SUCCEEDED(hr))
1368 IClassFactory_Release(pcf);
1370 return hr;
1373 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1375 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1376 HRESULT hr;
1378 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1380 hr = get_class_object(clsctx);
1382 CoUninitialize();
1384 return hr;
1387 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1389 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1390 HRESULT hr;
1391 IClassFactory *pcf;
1392 IMultiQI *pMQI;
1394 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1396 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1397 (void **)&pcf);
1399 if (SUCCEEDED(hr))
1401 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1402 if (SUCCEEDED(hr))
1403 IMultiQI_Release(pMQI);
1404 IClassFactory_Release(pcf);
1407 CoUninitialize();
1409 return hr;
1412 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1414 HRESULT hr;
1415 DWORD cookie;
1417 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1419 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1420 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1422 CoUninitialize();
1424 return hr;
1427 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1429 DWORD cookie = (DWORD_PTR)pv;
1430 HRESULT hr;
1432 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1434 hr = CoRevokeClassObject(cookie);
1436 CoUninitialize();
1438 return hr;
1441 static void test_registered_object_thread_affinity(void)
1443 HRESULT hr;
1444 DWORD cookie;
1445 HANDLE thread;
1446 DWORD tid;
1447 DWORD exitcode;
1449 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1451 /* CLSCTX_INPROC_SERVER */
1453 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1454 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1455 ok_ole_success(hr, "CoRegisterClassObject");
1457 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1458 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1459 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1460 GetExitCodeThread(thread, &exitcode);
1461 hr = exitcode;
1462 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1463 "registered in different thread should return REGDB_E_CLASSNOTREG "
1464 "instead of 0x%08x\n", hr);
1466 hr = get_class_object(CLSCTX_INPROC_SERVER);
1467 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1468 "thread should return S_OK instead of 0x%08x\n", hr);
1470 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1471 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1472 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1473 GetExitCodeThread(thread, &exitcode);
1474 hr = exitcode;
1475 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1477 hr = CoRevokeClassObject(cookie);
1478 ok_ole_success(hr, "CoRevokeClassObject");
1480 /* CLSCTX_LOCAL_SERVER */
1482 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1483 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1484 ok_ole_success(hr, "CoRegisterClassObject");
1486 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1487 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1488 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1490 MSG msg;
1491 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1493 TranslateMessage(&msg);
1494 DispatchMessageA(&msg);
1497 GetExitCodeThread(thread, &exitcode);
1498 hr = exitcode;
1499 ok(hr == S_OK, "CoGetClassObject on local server object "
1500 "registered in different thread should return S_OK "
1501 "instead of 0x%08x\n", hr);
1503 hr = get_class_object(CLSCTX_LOCAL_SERVER);
1504 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1505 "thread should return S_OK instead of 0x%08x\n", hr);
1507 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid);
1508 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1509 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1510 GetExitCodeThread(thread, &exitcode);
1511 hr = exitcode;
1512 ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different "
1513 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1515 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1516 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1517 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1518 GetExitCodeThread(thread, &exitcode);
1519 hr = exitcode;
1520 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1521 "thread should return S_OK instead of 0x%08x\n", hr);
1523 hr = CoRevokeClassObject(cookie);
1524 ok_ole_success(hr, "CoRevokeClassObject");
1526 CoUninitialize();
1529 static DWORD CALLBACK free_libraries_thread(LPVOID p)
1531 CoFreeUnusedLibraries();
1532 return 0;
1535 static inline BOOL is_module_loaded(const char *module)
1537 return GetModuleHandleA(module) != 0;
1540 static void test_CoFreeUnusedLibraries(void)
1542 HRESULT hr;
1543 IUnknown *pUnk;
1544 DWORD tid;
1545 HANDLE thread;
1547 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1549 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1551 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1552 if (hr == REGDB_E_CLASSNOTREG)
1554 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1555 CoUninitialize();
1556 return;
1558 ok_ole_success(hr, "CoCreateInstance");
1560 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1562 ok(pUnk != NULL ||
1563 broken(pUnk == NULL), /* win9x */
1564 "Expected a valid pointer\n");
1565 if (pUnk)
1566 IUnknown_Release(pUnk);
1568 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1570 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1571 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1572 CloseHandle(thread);
1574 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1576 CoFreeUnusedLibraries();
1578 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1580 CoUninitialize();
1583 static void test_CoGetObjectContext(void)
1585 HRESULT hr;
1586 ULONG refs;
1587 IComThreadingInfo *pComThreadingInfo;
1588 IContextCallback *pContextCallback;
1589 IObjContext *pObjContext;
1590 APTTYPE apttype;
1591 THDTYPE thdtype;
1592 struct info info;
1593 HANDLE thread;
1594 DWORD tid, exitcode;
1596 if (!pCoGetObjectContext)
1598 skip("CoGetObjectContext not present\n");
1599 return;
1602 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1603 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1604 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1606 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1607 thread has already done so */
1609 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
1610 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1612 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
1613 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1615 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1616 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1618 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1620 pComThreadingInfo = NULL;
1621 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1622 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1623 IComThreadingInfo_Release(pComThreadingInfo);
1625 SetEvent(info.stop);
1626 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1628 GetExitCodeThread(thread, &exitcode);
1629 hr = exitcode;
1630 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1632 CloseHandle(thread);
1633 CloseHandle(info.wait);
1634 CloseHandle(info.stop);
1636 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1638 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1639 ok_ole_success(hr, "CoGetObjectContext");
1641 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1642 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1643 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1645 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1646 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1647 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1649 refs = IComThreadingInfo_Release(pComThreadingInfo);
1650 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1652 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1653 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1655 if (hr == S_OK)
1657 refs = IContextCallback_Release(pContextCallback);
1658 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1661 CoUninitialize();
1663 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1665 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1666 ok_ole_success(hr, "CoGetObjectContext");
1668 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1669 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1670 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1672 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1673 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1674 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1676 refs = IComThreadingInfo_Release(pComThreadingInfo);
1677 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1679 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1680 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1682 if (hr == S_OK)
1684 refs = IContextCallback_Release(pContextCallback);
1685 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1688 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1689 ok_ole_success(hr, "CoGetObjectContext");
1691 refs = IObjContext_Release(pObjContext);
1692 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
1694 CoUninitialize();
1697 typedef struct {
1698 IUnknown IUnknown_iface;
1699 LONG refs;
1700 } Test_CallContext;
1702 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
1704 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
1707 static HRESULT WINAPI Test_CallContext_QueryInterface(
1708 IUnknown *iface,
1709 REFIID riid,
1710 LPVOID *ppvObj)
1712 if (ppvObj == NULL) return E_POINTER;
1714 if (IsEqualGUID(riid, &IID_IUnknown))
1716 *ppvObj = iface;
1717 IUnknown_AddRef(iface);
1718 return S_OK;
1721 *ppvObj = NULL;
1722 return E_NOINTERFACE;
1725 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
1727 Test_CallContext *This = impl_from_IUnknown(iface);
1728 return InterlockedIncrement(&This->refs);
1731 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
1733 Test_CallContext *This = impl_from_IUnknown(iface);
1734 ULONG refs = InterlockedDecrement(&This->refs);
1735 if (!refs)
1736 HeapFree(GetProcessHeap(), 0, This);
1737 return refs;
1740 static const IUnknownVtbl TestCallContext_Vtbl =
1742 Test_CallContext_QueryInterface,
1743 Test_CallContext_AddRef,
1744 Test_CallContext_Release
1747 static void test_CoGetCallContext(void)
1749 HRESULT hr;
1750 ULONG refs;
1751 IUnknown *pUnk;
1752 Test_CallContext *test_object;
1754 if (!pCoSwitchCallContext)
1756 skip("CoSwitchCallContext not present\n");
1757 return;
1760 CoInitialize(NULL);
1762 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
1763 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
1764 test_object->refs = 1;
1766 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1767 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1769 pUnk = (IUnknown*)0xdeadbeef;
1770 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
1771 ok_ole_success(hr, "CoSwitchCallContext");
1772 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
1773 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1774 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1775 IUnknown_Release(&test_object->IUnknown_iface);
1777 pUnk = (IUnknown*)0xdeadbeef;
1778 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1779 ok_ole_success(hr, "CoGetCallContext");
1780 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1781 &test_object->IUnknown_iface, pUnk);
1782 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1783 ok(refs == 3, "Expected refcount 3, got %d\n", refs);
1784 IUnknown_Release(&test_object->IUnknown_iface);
1785 IUnknown_Release(pUnk);
1787 pUnk = (IUnknown*)0xdeadbeef;
1788 hr = pCoSwitchCallContext(NULL, &pUnk);
1789 ok_ole_success(hr, "CoSwitchCallContext");
1790 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1791 &test_object->IUnknown_iface, pUnk);
1792 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1793 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1794 IUnknown_Release(&test_object->IUnknown_iface);
1796 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1797 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1799 IUnknown_Release(&test_object->IUnknown_iface);
1801 CoUninitialize();
1804 static void test_CoGetContextToken(void)
1806 HRESULT hr;
1807 ULONG refs;
1808 ULONG_PTR token;
1809 IObjContext *ctx;
1810 struct info info;
1811 HANDLE thread;
1812 DWORD tid, exitcode;
1814 if (!pCoGetContextToken)
1816 win_skip("CoGetContextToken not present\n");
1817 return;
1820 token = 0xdeadbeef;
1821 hr = pCoGetContextToken(&token);
1822 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
1823 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
1825 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1826 thread has already done so */
1828 info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
1829 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1831 info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
1832 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1834 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1835 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1837 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1839 token = 0;
1840 hr = pCoGetContextToken(&token);
1841 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1843 SetEvent(info.stop);
1844 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1846 GetExitCodeThread(thread, &exitcode);
1847 hr = exitcode;
1848 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1850 CloseHandle(thread);
1851 CloseHandle(info.wait);
1852 CloseHandle(info.stop);
1854 CoInitialize(NULL);
1856 hr = pCoGetContextToken(NULL);
1857 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
1859 token = 0;
1860 hr = pCoGetContextToken(&token);
1861 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1862 ok(token, "Expected token != 0\n");
1864 refs = IUnknown_AddRef((IUnknown *)token);
1865 todo_wine ok(refs == 1, "Expected 1, got %u\n", refs);
1867 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
1868 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1869 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1871 refs = IUnknown_AddRef((IUnknown *)ctx);
1872 todo_wine ok(refs == 3, "Expected 3, got %u\n", refs);
1874 refs = IUnknown_Release((IUnknown *)ctx);
1875 todo_wine ok(refs == 2, "Expected 2, got %u\n", refs);
1877 refs = IUnknown_Release((IUnknown *)token);
1878 ok(refs == 1, "Expected 1, got %u\n", refs);
1880 /* CoGetContextToken does not add a reference */
1881 token = 0;
1882 hr = pCoGetContextToken(&token);
1883 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1884 ok(token, "Expected token != 0\n");
1885 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1887 refs = IUnknown_AddRef((IUnknown *)ctx);
1888 ok(refs == 2, "Expected 1, got %u\n", refs);
1890 refs = IUnknown_Release((IUnknown *)ctx);
1891 ok(refs == 1, "Expected 0, got %u\n", refs);
1893 refs = IUnknown_Release((IUnknown *)ctx);
1894 ok(refs == 0, "Expected 0, got %u\n", refs);
1896 CoUninitialize();
1899 static void test_CoGetTreatAsClass(void)
1901 HRESULT hr;
1902 CLSID out;
1903 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1905 if (!pCoGetTreatAsClass)
1907 win_skip("CoGetTreatAsClass not present\n");
1908 return;
1910 hr = pCoGetTreatAsClass(&deadbeef,&out);
1911 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
1912 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
1915 static void test_CoInitializeEx(void)
1917 HRESULT hr;
1919 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1920 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
1922 /* Calling OleInitialize for the first time should yield S_OK even with
1923 * apartment already initialized by previous CoInitialize(Ex) calls. */
1924 hr = OleInitialize(NULL);
1925 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
1927 /* Subsequent calls to OleInitialize should return S_FALSE */
1928 hr = OleInitialize(NULL);
1929 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
1931 /* Cleanup */
1932 CoUninitialize();
1933 OleUninitialize();
1936 static void test_OleRegGetMiscStatus(void)
1938 ULONG_PTR cookie;
1939 HANDLE handle;
1940 DWORD status;
1941 HRESULT hr;
1943 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, NULL);
1944 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1946 status = 0xdeadbeef;
1947 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
1948 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
1949 ok(status == 0, "got 0x%08x\n", status);
1951 status = -1;
1952 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
1953 ok(hr == S_OK, "got 0x%08x\n", hr);
1954 ok(status == 0, "got 0x%08x\n", status);
1956 if ((handle = activate_context(actctx_manifest, &cookie)))
1958 status = 0;
1959 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
1960 ok(hr == S_OK, "got 0x%08x\n", hr);
1961 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
1963 /* context data takes precedence over registration info */
1964 status = 0;
1965 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
1966 ok(hr == S_OK, "got 0x%08x\n", hr);
1967 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
1969 /* there's no such attribute in context */
1970 status = -1;
1971 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status);
1972 ok(hr == S_OK, "got 0x%08x\n", hr);
1973 ok(status == 0, "got 0x%08x\n", status);
1975 pDeactivateActCtx(0, cookie);
1976 pReleaseActCtx(handle);
1980 static void init_funcs(void)
1982 HMODULE hOle32 = GetModuleHandleA("ole32");
1983 HMODULE hAdvapi32 = GetModuleHandleA("advapi32");
1984 HMODULE hkernel32 = GetModuleHandleA("kernel32");
1986 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
1987 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
1988 pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
1989 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
1990 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
1991 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
1993 pActivateActCtx = (void*)GetProcAddress(hkernel32, "ActivateActCtx");
1994 pCreateActCtxW = (void*)GetProcAddress(hkernel32, "CreateActCtxW");
1995 pDeactivateActCtx = (void*)GetProcAddress(hkernel32, "DeactivateActCtx");
1996 pReleaseActCtx = (void*)GetProcAddress(hkernel32, "ReleaseActCtx");
1999 START_TEST(compobj)
2001 init_funcs();
2003 if (!pCoInitializeEx)
2005 trace("You need DCOM95 installed to run this test\n");
2006 return;
2009 if (!pCreateActCtxW)
2010 win_skip("Activation contexts are not supported, some tests will be skipped.\n");
2012 test_ProgIDFromCLSID();
2013 test_CLSIDFromProgID();
2014 test_CLSIDFromString();
2015 test_IIDFromString();
2016 test_StringFromGUID2();
2017 test_CoCreateInstance();
2018 test_ole_menu();
2019 test_CoGetClassObject();
2020 test_CoRegisterMessageFilter();
2021 test_CoRegisterPSClsid();
2022 test_CoGetPSClsid();
2023 test_CoUnmarshalInterface();
2024 test_CoGetInterfaceAndReleaseStream();
2025 test_CoMarshalInterface();
2026 test_CoMarshalInterThreadInterfaceInStream();
2027 test_CoRegisterClassObject();
2028 test_registered_object_thread_affinity();
2029 test_CoFreeUnusedLibraries();
2030 test_CoGetObjectContext();
2031 test_CoGetCallContext();
2032 test_CoGetContextToken();
2033 test_CoGetTreatAsClass();
2034 test_CoInitializeEx();
2035 test_OleRegGetMiscStatus();