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
29 #define USE_COM_CONTEXT_DEF
33 #include "urlmon.h" /* for CLSID_FileProtocol */
38 #include "wine/test.h"
40 /* functions that are not present on all versions of Windows */
41 static HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
42 static HRESULT (WINAPI
* pCoGetObjectContext
)(REFIID riid
, LPVOID
*ppv
);
43 static HRESULT (WINAPI
* pCoSwitchCallContext
)(IUnknown
*pObject
, IUnknown
**ppOldObject
);
44 static HRESULT (WINAPI
* pCoGetTreatAsClass
)(REFCLSID clsidOld
, LPCLSID pClsidNew
);
45 static HRESULT (WINAPI
* pCoTreatAsClass
)(REFCLSID clsidOld
, REFCLSID pClsidNew
);
46 static HRESULT (WINAPI
* pCoGetContextToken
)(ULONG_PTR
*token
);
47 static LONG (WINAPI
* pRegDeleteKeyExA
)(HKEY
, LPCSTR
, REGSAM
, DWORD
);
48 static LONG (WINAPI
* pRegOverridePredefKey
)(HKEY key
, HKEY override
);
50 static BOOL (WINAPI
*pActivateActCtx
)(HANDLE
,ULONG_PTR
*);
51 static HANDLE (WINAPI
*pCreateActCtxW
)(PCACTCTXW
);
52 static BOOL (WINAPI
*pDeactivateActCtx
)(DWORD
,ULONG_PTR
);
53 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, LPBOOL
);
54 static void (WINAPI
*pReleaseActCtx
)(HANDLE
);
56 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
57 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
58 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
60 static const CLSID CLSID_non_existent
= { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
61 static const CLSID CLSID_StdFont
= { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
62 static const GUID IID_Testiface
= { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
63 static const GUID IID_Testiface2
= { 0x32222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
64 static const GUID IID_Testiface3
= { 0x42222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
65 static const GUID IID_Testiface4
= { 0x52222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
66 static const GUID IID_Testiface5
= { 0x62222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
67 static const GUID IID_Testiface6
= { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
68 static const GUID IID_TestPS
= { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } };
70 DEFINE_GUID(CLSID_InProcFreeMarshaler
, 0x0000033a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
72 static const WCHAR stdfont
[] = {'S','t','d','F','o','n','t',0};
73 static const WCHAR wszNonExistent
[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
74 static const WCHAR wszCLSID_StdFont
[] =
76 '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
77 '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
79 static const WCHAR progidW
[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
80 static const WCHAR cf_brokenW
[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
81 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0};
83 DEFINE_GUID(IID_IWineTest
, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
84 DEFINE_GUID(CLSID_WineOOPTest
, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
88 static void LockModule(void)
90 InterlockedIncrement(&cLocks
);
93 static void UnlockModule(void)
95 InterlockedDecrement(&cLocks
);
98 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
103 if (ppvObj
== NULL
) return E_POINTER
;
105 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
106 IsEqualGUID(riid
, &IID_IClassFactory
))
109 IClassFactory_AddRef(iface
);
114 return E_NOINTERFACE
;
117 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
120 return 2; /* non-heap-based object */
123 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
126 return 1; /* non-heap-based object */
129 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
130 LPCLASSFACTORY iface
,
136 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
137 return E_NOINTERFACE
;
140 static HRESULT WINAPI
Test_IClassFactory_LockServer(
141 LPCLASSFACTORY iface
,
147 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
149 Test_IClassFactory_QueryInterface
,
150 Test_IClassFactory_AddRef
,
151 Test_IClassFactory_Release
,
152 Test_IClassFactory_CreateInstance
,
153 Test_IClassFactory_LockServer
156 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
158 static WCHAR manifest_path
[MAX_PATH
];
160 static BOOL
create_manifest_file(const char *filename
, const char *manifest
)
165 WCHAR path
[MAX_PATH
];
167 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
168 GetFullPathNameW(path
, sizeof(manifest_path
)/sizeof(WCHAR
), manifest_path
, NULL
);
170 manifest_len
= strlen(manifest
);
171 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
172 FILE_ATTRIBUTE_NORMAL
, NULL
);
173 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
174 if(file
== INVALID_HANDLE_VALUE
)
176 WriteFile(file
, manifest
, manifest_len
, &size
, NULL
);
182 static HANDLE
activate_context(const char *manifest
, ULONG_PTR
*cookie
)
184 WCHAR path
[MAX_PATH
];
189 if (!pCreateActCtxW
) return NULL
;
191 create_manifest_file("file.manifest", manifest
);
193 MultiByteToWideChar( CP_ACP
, 0, "file.manifest", -1, path
, MAX_PATH
);
194 memset(&actctx
, 0, sizeof(ACTCTXW
));
195 actctx
.cbSize
= sizeof(ACTCTXW
);
196 actctx
.lpSource
= path
;
198 handle
= pCreateActCtxW(&actctx
);
199 ok(handle
!= INVALID_HANDLE_VALUE
|| broken(handle
== INVALID_HANDLE_VALUE
) /* some old XP/2k3 versions */,
200 "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
201 if (handle
== INVALID_HANDLE_VALUE
)
203 win_skip("activation context generation failed, some tests will be skipped\n");
207 ok(actctx
.cbSize
== sizeof(ACTCTXW
), "actctx.cbSize=%d\n", actctx
.cbSize
);
208 ok(actctx
.dwFlags
== 0, "actctx.dwFlags=%d\n", actctx
.dwFlags
);
209 ok(actctx
.lpSource
== path
, "actctx.lpSource=%p\n", actctx
.lpSource
);
210 ok(actctx
.wProcessorArchitecture
== 0, "actctx.wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
211 ok(actctx
.wLangId
== 0, "actctx.wLangId=%d\n", actctx
.wLangId
);
212 ok(actctx
.lpAssemblyDirectory
== NULL
, "actctx.lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
213 ok(actctx
.lpResourceName
== NULL
, "actctx.lpResourceName=%p\n", actctx
.lpResourceName
);
214 ok(actctx
.lpApplicationName
== NULL
, "actctx.lpApplicationName=%p\n", actctx
.lpApplicationName
);
215 ok(actctx
.hModule
== NULL
, "actctx.hModule=%p\n", actctx
.hModule
);
217 DeleteFileA("file.manifest");
221 ret
= pActivateActCtx(handle
, cookie
);
222 ok(ret
, "ActivateActCtx failed: %u\n", GetLastError());
228 static const char actctx_manifest
[] =
229 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
230 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
231 " publicKeyToken=\"6595b6414666f1df\" />"
232 "<file name=\"testlib.dll\">"
234 " clsid=\"{0000033a-0000-0000-c000-000000000046}\""
235 " progid=\"FTMarshal\""
238 " clsid=\"{5201163f-8164-4fd0-a1a2-5d5a3654d3bd}\""
239 " progid=\"WineOOPTest\""
241 " <comClass description=\"Test com class\""
242 " clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
243 " progid=\"ProgId.ProgId\""
244 " miscStatusIcon=\"recomposeonresize\""
246 " <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb851}\""
247 " progid=\"CustomFont\""
248 " miscStatusIcon=\"recomposeonresize\""
249 " miscStatusContent=\"insideout\""
251 " <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
252 " progid=\"StdFont\""
254 " <comClass clsid=\"{62222222-1234-1234-1234-56789abcdef0}\" >"
255 " <progid>ProgId.ProgId.1</progid>"
257 " <comInterfaceProxyStub "
259 " iid=\"{22222222-1234-1234-1234-56789abcdef0}\""
260 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
263 " <comInterfaceExternalProxyStub "
264 " name=\"Iifaceps2\""
265 " iid=\"{32222222-1234-1234-1234-56789abcdef0}\""
267 " <comInterfaceExternalProxyStub "
268 " name=\"Iifaceps3\""
269 " iid=\"{42222222-1234-1234-1234-56789abcdef0}\""
270 " proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
272 " <comInterfaceExternalProxyStub "
273 " name=\"Iifaceps4\""
274 " iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
275 " proxyStubClsid32=\"{00000000-0000-0000-0000-000000000000}\""
278 " clsid=\"{72222222-1234-1234-1234-56789abcdef0}\""
281 " <progid>clrprogid.1</progid>"
285 DEFINE_GUID(CLSID_Testclass
, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
287 static void test_ProgIDFromCLSID(void)
289 ULONG_PTR cookie
= 0;
294 hr
= ProgIDFromCLSID(&CLSID_StdFont
, &progid
);
295 ok(hr
== S_OK
, "ProgIDFromCLSID failed with error 0x%08x\n", hr
);
298 ok(!lstrcmpiW(progid
, stdfont
), "Didn't get expected prog ID\n");
299 CoTaskMemFree(progid
);
302 progid
= (LPWSTR
)0xdeadbeef;
303 hr
= ProgIDFromCLSID(&CLSID_non_existent
, &progid
);
304 ok(hr
== REGDB_E_CLASSNOTREG
, "ProgIDFromCLSID returned %08x\n", hr
);
305 ok(progid
== NULL
, "ProgIDFromCLSID returns with progid %p\n", progid
);
307 hr
= ProgIDFromCLSID(&CLSID_StdFont
, NULL
);
308 ok(hr
== E_INVALIDARG
, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr
);
310 if ((handle
= activate_context(actctx_manifest
, &cookie
)))
312 static const WCHAR customfontW
[] = {'C','u','s','t','o','m','F','o','n','t',0};
314 hr
= ProgIDFromCLSID(&CLSID_non_existent
, &progid
);
315 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
316 ok(!lstrcmpiW(progid
, progidW
), "got %s\n", wine_dbgstr_w(progid
));
317 CoTaskMemFree(progid
);
319 /* try something registered and redirected */
321 hr
= ProgIDFromCLSID(&CLSID_StdFont
, &progid
);
322 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
323 ok(!lstrcmpiW(progid
, customfontW
), "got wrong progid %s\n", wine_dbgstr_w(progid
));
324 CoTaskMemFree(progid
);
326 /* classes without default progid, progid list is not used */
327 hr
= ProgIDFromCLSID(&IID_Testiface5
, &progid
);
328 ok(hr
== REGDB_E_CLASSNOTREG
, "got 0x%08x\n", hr
);
330 hr
= ProgIDFromCLSID(&IID_Testiface6
, &progid
);
331 ok(hr
== REGDB_E_CLASSNOTREG
, "got 0x%08x\n", hr
);
333 pDeactivateActCtx(0, cookie
);
334 pReleaseActCtx(handle
);
338 static void test_CLSIDFromProgID(void)
340 ULONG_PTR cookie
= 0;
343 HRESULT hr
= CLSIDFromProgID(stdfont
, &clsid
);
344 ok(hr
== S_OK
, "CLSIDFromProgID failed with error 0x%08x\n", hr
);
345 ok(IsEqualCLSID(&clsid
, &CLSID_StdFont
), "clsid wasn't equal to CLSID_StdFont\n");
347 hr
= CLSIDFromString(stdfont
, &clsid
);
348 ok_ole_success(hr
, "CLSIDFromString");
349 ok(IsEqualCLSID(&clsid
, &CLSID_StdFont
), "clsid wasn't equal to CLSID_StdFont\n");
351 /* test some failure cases */
353 hr
= CLSIDFromProgID(wszNonExistent
, NULL
);
354 ok(hr
== E_INVALIDARG
, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
356 hr
= CLSIDFromProgID(NULL
, &clsid
);
357 ok(hr
== E_INVALIDARG
, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
359 memset(&clsid
, 0xcc, sizeof(clsid
));
360 hr
= CLSIDFromProgID(wszNonExistent
, &clsid
);
361 ok(hr
== CO_E_CLASSSTRING
, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr
);
362 ok(IsEqualCLSID(&clsid
, &CLSID_NULL
), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
364 /* fails without proper context */
365 memset(&clsid
, 0xcc, sizeof(clsid
));
366 hr
= CLSIDFromProgID(progidW
, &clsid
);
367 ok(hr
== CO_E_CLASSSTRING
, "got 0x%08x\n", hr
);
368 ok(IsEqualCLSID(&clsid
, &CLSID_NULL
), "wrong clsid\n");
370 if ((handle
= activate_context(actctx_manifest
, &cookie
)))
374 memset(&clsid
, 0xcc, sizeof(clsid
));
375 hr
= CLSIDFromProgID(wszNonExistent
, &clsid
);
376 ok(hr
== CO_E_CLASSSTRING
, "got 0x%08x\n", hr
);
377 ok(IsEqualCLSID(&clsid
, &CLSID_NULL
), "should have zero CLSID on failure\n");
379 /* CLSIDFromString() doesn't check activation context */
380 hr
= CLSIDFromString(progidW
, &clsid
);
381 ok(hr
== CO_E_CLASSSTRING
, "got 0x%08x\n", hr
);
384 hr
= CLSIDFromProgID(progidW
, &clsid
);
385 /* it returns generated CLSID here */
386 ok(!IsEqualCLSID(&clsid
, &CLSID_non_existent
) && !IsEqualCLSID(&clsid
, &CLSID_NULL
),
387 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid
));
389 /* duplicate progid present in context - returns generated guid here too */
391 hr
= CLSIDFromProgID(stdfont
, &clsid
);
392 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
393 clsid1
= CLSID_StdFont
;
394 /* that's where it differs from StdFont */
395 clsid1
.Data4
[7] = 0x52;
396 ok(!IsEqualCLSID(&clsid
, &CLSID_StdFont
) && !IsEqualCLSID(&clsid
, &CLSID_NULL
) && !IsEqualCLSID(&clsid
, &clsid1
),
397 "got %s\n", wine_dbgstr_guid(&clsid
));
399 pDeactivateActCtx(0, cookie
);
400 pReleaseActCtx(handle
);
404 static void test_CLSIDFromString(void)
407 WCHAR wszCLSID_Broken
[50];
410 HRESULT hr
= CLSIDFromString(wszCLSID_StdFont
, &clsid
);
411 ok_ole_success(hr
, "CLSIDFromString");
412 ok(IsEqualCLSID(&clsid
, &CLSID_StdFont
), "clsid wasn't equal to CLSID_StdFont\n");
414 memset(&clsid
, 0xab, sizeof(clsid
));
415 hr
= CLSIDFromString(NULL
, &clsid
);
416 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
417 ok(IsEqualCLSID(&clsid
, &CLSID_NULL
), "clsid wasn't equal to CLSID_NULL\n");
419 /* string is longer, but starts with a valid CLSID */
420 memset(&clsid
, 0, sizeof(clsid
));
421 hr
= CLSIDFromString(cf_brokenW
, &clsid
);
422 ok(hr
== CO_E_CLASSSTRING
, "got 0x%08x\n", hr
);
423 ok(IsEqualCLSID(&clsid
, &IID_IClassFactory
), "got %s\n", wine_dbgstr_guid(&clsid
));
425 lstrcpyW(wszCLSID_Broken
, wszCLSID_StdFont
);
426 for(i
= lstrlenW(wszCLSID_StdFont
); i
< 49; i
++)
427 wszCLSID_Broken
[i
] = 'A';
428 wszCLSID_Broken
[i
] = '\0';
430 memset(&clsid
, 0, sizeof(CLSID
));
431 hr
= CLSIDFromString(wszCLSID_Broken
, &clsid
);
432 ok(hr
== CO_E_CLASSSTRING
, "Got %08x\n", hr
);
433 ok(IsEqualCLSID(&clsid
, &CLSID_StdFont
), "clsid wasn't equal to CLSID_StdFont\n");
435 wszCLSID_Broken
[lstrlenW(wszCLSID_StdFont
)-1] = 'A';
436 memset(&clsid
, 0, sizeof(CLSID
));
437 hr
= CLSIDFromString(wszCLSID_Broken
, &clsid
);
438 ok(hr
== CO_E_CLASSSTRING
, "Got %08x\n", hr
);
439 ok(IsEqualCLSID(&clsid
, &CLSID_StdFont
), "clsid wasn't equal to CLSID_StdFont\n");
441 wszCLSID_Broken
[lstrlenW(wszCLSID_StdFont
)] = '\0';
442 memset(&clsid
, 0, sizeof(CLSID
));
443 hr
= CLSIDFromString(wszCLSID_Broken
, &clsid
);
444 ok(hr
== CO_E_CLASSSTRING
, "Got %08x\n", hr
);
445 ok(IsEqualCLSID(&clsid
, &CLSID_StdFont
), "clsid wasn't equal to CLSID_StdFont\n");
447 wszCLSID_Broken
[lstrlenW(wszCLSID_StdFont
)-1] = '\0';
448 memset(&clsid
, 0, sizeof(CLSID
));
449 hr
= CLSIDFromString(wszCLSID_Broken
, &clsid
);
450 ok(hr
== CO_E_CLASSSTRING
, "Got %08x\n", hr
);
451 ok(IsEqualCLSID(&clsid
, &CLSID_StdFont
), "clsid wasn't equal to CLSID_StdFont\n");
453 memset(&clsid
, 0xcc, sizeof(CLSID
));
454 hr
= CLSIDFromString(wszCLSID_Broken
+1, &clsid
);
455 ok(hr
== CO_E_CLASSSTRING
, "Got %08x\n", hr
);
456 ok(IsEqualCLSID(&clsid
, &CLSID_NULL
), "clsid wasn't equal to CLSID_NULL\n");
458 wszCLSID_Broken
[9] = '*';
459 memset(&clsid
, 0xcc, sizeof(CLSID
));
460 hr
= CLSIDFromString(wszCLSID_Broken
, &clsid
);
461 ok(hr
== CO_E_CLASSSTRING
, "Got %08x\n", hr
);
462 ok(clsid
.Data1
== CLSID_StdFont
.Data1
, "Got %08x\n", clsid
.Data1
);
463 ok(clsid
.Data2
== 0xcccc, "Got %04x\n", clsid
.Data2
);
465 wszCLSID_Broken
[3] = '*';
466 memset(&clsid
, 0xcc, sizeof(CLSID
));
467 hr
= CLSIDFromString(wszCLSID_Broken
, &clsid
);
468 ok(hr
== CO_E_CLASSSTRING
, "Got %08x\n", hr
);
469 ok(clsid
.Data1
== 0xb, "Got %08x\n", clsid
.Data1
);
470 ok(clsid
.Data2
== 0xcccc, "Got %04x\n", clsid
.Data2
);
472 wszCLSID_Broken
[3] = '\0';
473 memset(&clsid
, 0xcc, sizeof(CLSID
));
474 hr
= CLSIDFromString(wszCLSID_Broken
, &clsid
);
475 ok(hr
== CO_E_CLASSSTRING
, "Got %08x\n", hr
);
476 ok(clsid
.Data1
== 0xb, "Got %08x\n", clsid
.Data1
);
477 ok(clsid
.Data2
== 0xcccc, "Got %04x\n", clsid
.Data2
);
480 static void test_IIDFromString(void)
482 static const WCHAR cfW
[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
483 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
484 static const WCHAR brokenW
[] = {'{','0','0','0','0','0','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 static const WCHAR broken2W
[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
487 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
488 static const WCHAR broken3W
[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
489 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
493 hr
= IIDFromString(wszCLSID_StdFont
, &iid
);
494 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
495 ok(IsEqualIID(&iid
, &CLSID_StdFont
), "got iid %s\n", wine_dbgstr_guid(&iid
));
497 memset(&iid
, 0xab, sizeof(iid
));
498 hr
= IIDFromString(NULL
, &iid
);
499 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
500 ok(IsEqualIID(&iid
, &CLSID_NULL
), "got iid %s\n", wine_dbgstr_guid(&iid
));
502 hr
= IIDFromString(cfW
, &iid
);
503 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
504 ok(IsEqualIID(&iid
, &IID_IClassFactory
), "got iid %s\n", wine_dbgstr_guid(&iid
));
506 /* string starts with a valid IID but is longer */
507 memset(&iid
, 0xab, sizeof(iid
));
508 hr
= IIDFromString(cf_brokenW
, &iid
);
509 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
510 ok(iid
.Data1
== 0xabababab, "Got %08x\n", iid
.Data1
);
512 /* invalid IID in a valid format */
513 memset(&iid
, 0xab, sizeof(iid
));
514 hr
= IIDFromString(brokenW
, &iid
);
515 ok(hr
== CO_E_IIDSTRING
, "got 0x%08x\n", hr
);
516 ok(iid
.Data1
== 0x00000001, "Got %08x\n", iid
.Data1
);
518 memset(&iid
, 0xab, sizeof(iid
));
519 hr
= IIDFromString(broken2W
, &iid
);
520 ok(hr
== CO_E_IIDSTRING
, "got 0x%08x\n", hr
);
521 ok(iid
.Data1
== 0x00000001, "Got %08x\n", iid
.Data1
);
523 /* format is broken, but string length is okay */
524 memset(&iid
, 0xab, sizeof(iid
));
525 hr
= IIDFromString(broken3W
, &iid
);
526 ok(hr
== CO_E_IIDSTRING
, "got 0x%08x\n", hr
);
527 ok(iid
.Data1
== 0xabababab, "Got %08x\n", iid
.Data1
);
530 memset(&iid
, 0xab, sizeof(iid
));
531 hr
= IIDFromString(wszNonExistent
, &iid
);
532 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
533 ok(iid
.Data1
== 0xabababab, "Got %08x\n", iid
.Data1
);
536 memset(&iid
, 0xab, sizeof(iid
));
537 hr
= IIDFromString(stdfont
, &iid
);
538 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
539 ok(iid
.Data1
== 0xabababab, "Got %08x\n", iid
.Data1
);
542 static void test_StringFromGUID2(void)
547 /* invalid pointer */
548 SetLastError(0xdeadbeef);
549 len
= StringFromGUID2(NULL
,str
,50);
550 ok(len
== 0, "len: %d (expected 0)\n", len
);
551 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
553 /* Test corner cases for buffer size */
554 len
= StringFromGUID2(&CLSID_StdFont
,str
,50);
555 ok(len
== 39, "len: %d (expected 39)\n", len
);
556 ok(!lstrcmpiW(str
, wszCLSID_StdFont
),"string wasn't equal for CLSID_StdFont\n");
558 memset(str
,0,sizeof str
);
559 len
= StringFromGUID2(&CLSID_StdFont
,str
,39);
560 ok(len
== 39, "len: %d (expected 39)\n", len
);
561 ok(!lstrcmpiW(str
, wszCLSID_StdFont
),"string wasn't equal for CLSID_StdFont\n");
563 len
= StringFromGUID2(&CLSID_StdFont
,str
,38);
564 ok(len
== 0, "len: %d (expected 0)\n", len
);
566 len
= StringFromGUID2(&CLSID_StdFont
,str
,30);
567 ok(len
== 0, "len: %d (expected 0)\n", len
);
575 static DWORD CALLBACK
ole_initialize_thread(LPVOID pv
)
578 struct info
*info
= pv
;
580 hr
= pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
582 SetEvent(info
->wait
);
583 WaitForSingleObject(info
->stop
, 10000);
589 static void test_CoCreateInstance(void)
596 REFCLSID rclsid
= &CLSID_InternetZoneManager
;
598 pUnk
= (IUnknown
*)0xdeadbeef;
599 hr
= CoCreateInstance(rclsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
600 ok(hr
== CO_E_NOTINITIALIZED
, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
601 ok(pUnk
== NULL
, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk
);
605 /* test errors returned for non-registered clsids */
606 hr
= CoCreateInstance(&CLSID_non_existent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
607 ok(hr
== REGDB_E_CLASSNOTREG
, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
608 hr
= CoCreateInstance(&CLSID_non_existent
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pUnk
);
609 ok(hr
== REGDB_E_CLASSNOTREG
, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
610 hr
= CoCreateInstance(&CLSID_non_existent
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
611 ok(hr
== REGDB_E_CLASSNOTREG
, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
612 hr
= CoCreateInstance(&CLSID_non_existent
, NULL
, CLSCTX_REMOTE_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
613 ok(hr
== REGDB_E_CLASSNOTREG
, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
615 hr
= CoCreateInstance(rclsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
616 if(hr
== REGDB_E_CLASSNOTREG
)
618 skip("IE not installed so can't test CoCreateInstance\n");
623 ok_ole_success(hr
, "CoCreateInstance");
624 if(pUnk
) IUnknown_Release(pUnk
);
627 hr
= CoCreateInstance(rclsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
628 ok(hr
== CO_E_NOTINITIALIZED
, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
630 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
631 thread has already done so */
633 info
.wait
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
634 ok(info
.wait
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
636 info
.stop
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
637 ok(info
.stop
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
639 thread
= CreateThread(NULL
, 0, ole_initialize_thread
, &info
, 0, &tid
);
640 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
642 ok( !WaitForSingleObject(info
.wait
, 10000 ), "wait timed out\n" );
644 pUnk
= (IUnknown
*)0xdeadbeef;
645 hr
= CoCreateInstance(rclsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
646 ok(hr
== S_OK
, "CoCreateInstance should have returned S_OK instead of 0x%08x\n", hr
);
647 if (pUnk
) IUnknown_Release(pUnk
);
650 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
652 GetExitCodeThread(thread
, &exitcode
);
654 ok(hr
== S_OK
, "thread should have returned S_OK instead of 0x%08x\n", hr
);
657 CloseHandle(info
.wait
);
658 CloseHandle(info
.stop
);
661 static void test_CoGetClassObject(void)
664 HANDLE thread
, handle
;
669 REFCLSID rclsid
= &CLSID_InternetZoneManager
;
673 hr
= CoGetClassObject(rclsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IUnknown
, (void **)&pUnk
);
674 ok(hr
== CO_E_NOTINITIALIZED
, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
675 ok(pUnk
== NULL
, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk
);
677 hr
= CoGetClassObject(rclsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IUnknown
, NULL
);
678 ok(hr
== E_INVALIDARG
||
679 broken(hr
== CO_E_NOTINITIALIZED
), /* win9x */
680 "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
682 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
683 thread has already done so */
685 info
.wait
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
686 ok(info
.wait
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
688 info
.stop
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
689 ok(info
.stop
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
691 thread
= CreateThread(NULL
, 0, ole_initialize_thread
, &info
, 0, &tid
);
692 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
694 ok( !WaitForSingleObject(info
.wait
, 10000), "wait timed out\n" );
696 pUnk
= (IUnknown
*)0xdeadbeef;
697 hr
= CoGetClassObject(rclsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IUnknown
, (void **)&pUnk
);
698 if(hr
== REGDB_E_CLASSNOTREG
)
699 skip("IE not installed so can't test CoGetClassObject\n");
702 ok(hr
== S_OK
, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr
);
703 if (pUnk
) IUnknown_Release(pUnk
);
707 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
709 GetExitCodeThread(thread
, &exitcode
);
711 ok(hr
== S_OK
, "thread should have returned S_OK instead of 0x%08x\n", hr
);
714 CloseHandle(info
.wait
);
715 CloseHandle(info
.stop
);
717 if (!pRegOverridePredefKey
)
719 win_skip("RegOverridePredefKey not available\n");
723 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
725 hr
= CoGetClassObject(rclsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IUnknown
, (void **)&pUnk
);
728 IUnknown_Release(pUnk
);
730 res
= RegCreateKeyExA(HKEY_CURRENT_USER
, "Software\\Classes", 0, NULL
, 0,
731 KEY_ALL_ACCESS
, NULL
, &hkey
, NULL
);
732 ok(!res
, "RegCreateKeyEx returned %d\n", res
);
734 res
= pRegOverridePredefKey(HKEY_CLASSES_ROOT
, hkey
);
735 ok(!res
, "RegOverridePredefKey returned %d\n", res
);
737 hr
= CoGetClassObject(rclsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IUnknown
, (void **)&pUnk
);
738 ok(hr
== S_OK
, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr
);
740 res
= pRegOverridePredefKey(HKEY_CLASSES_ROOT
, NULL
);
741 ok(!res
, "RegOverridePredefKey returned %d\n", res
);
743 if (hr
== S_OK
) IUnknown_Release(pUnk
);
747 hr
= CoGetClassObject(&CLSID_InProcFreeMarshaler
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IUnknown
, (void **)&pUnk
);
748 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
749 IUnknown_Release(pUnk
);
751 /* context redefines FreeMarshaler CLSID */
752 if ((handle
= activate_context(actctx_manifest
, &cookie
)))
754 hr
= CoGetClassObject(&CLSID_InProcFreeMarshaler
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IUnknown
, (void **)&pUnk
);
755 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
756 IUnknown_Release(pUnk
);
758 pDeactivateActCtx(0, cookie
);
759 pReleaseActCtx(handle
);
765 static ATOM
register_dummy_class(void)
773 GetModuleHandleA(NULL
),
775 LoadCursorA(NULL
, (LPSTR
)IDC_ARROW
),
776 (HBRUSH
)(COLOR_BTNFACE
+1),
781 return RegisterClassA(&wc
);
784 static void test_ole_menu(void)
789 hwndFrame
= CreateWindowA((LPCSTR
)MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, NULL
);
790 hr
= OleSetMenuDescriptor(NULL
, hwndFrame
, NULL
, NULL
, NULL
);
791 todo_wine
ok_ole_success(hr
, "OleSetMenuDescriptor");
793 DestroyWindow(hwndFrame
);
797 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
799 if (ppvObj
== NULL
) return E_POINTER
;
801 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
802 IsEqualGUID(riid
, &IID_IClassFactory
))
805 IMessageFilter_AddRef(iface
);
809 return E_NOINTERFACE
;
812 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
814 return 2; /* non-heap object */
817 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
819 return 1; /* non-heap object */
822 static DWORD WINAPI
MessageFilter_HandleInComingCall(
823 IMessageFilter
*iface
,
825 HTASK threadIDCaller
,
827 LPINTERFACEINFO lpInterfaceInfo
)
829 trace("HandleInComingCall\n");
830 return SERVERCALL_ISHANDLED
;
833 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
834 IMessageFilter
*iface
,
835 HTASK threadIDCallee
,
839 trace("RetryRejectedCall\n");
843 static DWORD WINAPI
MessageFilter_MessagePending(
844 IMessageFilter
*iface
,
845 HTASK threadIDCallee
,
849 trace("MessagePending\n");
850 return PENDINGMSG_WAITNOPROCESS
;
853 static const IMessageFilterVtbl MessageFilter_Vtbl
=
855 MessageFilter_QueryInterface
,
856 MessageFilter_AddRef
,
857 MessageFilter_Release
,
858 MessageFilter_HandleInComingCall
,
859 MessageFilter_RetryRejectedCall
,
860 MessageFilter_MessagePending
863 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
865 static void test_CoRegisterMessageFilter(void)
868 IMessageFilter
*prev_filter
;
870 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
871 ok(hr
== CO_E_NOT_SUPPORTED
,
872 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
875 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
876 prev_filter
= (IMessageFilter
*)0xdeadbeef;
877 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
878 ok(hr
== CO_E_NOT_SUPPORTED
,
879 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
881 ok(prev_filter
== (IMessageFilter
*)0xdeadbeef,
882 "prev_filter should have been set to %p\n", prev_filter
);
885 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
887 hr
= CoRegisterMessageFilter(NULL
, NULL
);
888 ok_ole_success(hr
, "CoRegisterMessageFilter");
890 prev_filter
= (IMessageFilter
*)0xdeadbeef;
891 hr
= CoRegisterMessageFilter(NULL
, &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(&MessageFilter
, &prev_filter
);
896 ok_ole_success(hr
, "CoRegisterMessageFilter");
897 ok(prev_filter
== NULL
, "prev_filter should have been set to NULL instead of %p\n", prev_filter
);
899 hr
= CoRegisterMessageFilter(NULL
, NULL
);
900 ok_ole_success(hr
, "CoRegisterMessageFilter");
905 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
910 if (ppvObj
== NULL
) return E_POINTER
;
912 if (IsEqualIID(riid
, &IID_IUnknown
) ||
913 IsEqualIID(riid
, &IID_IWineTest
))
916 IUnknown_AddRef(iface
);
921 return E_NOINTERFACE
;
924 static ULONG WINAPI
Test_IUnknown_AddRef(IUnknown
*iface
)
926 return 2; /* non-heap-based object */
929 static ULONG WINAPI
Test_IUnknown_Release(IUnknown
*iface
)
931 return 1; /* non-heap-based object */
934 static const IUnknownVtbl TestUnknown_Vtbl
=
936 Test_IUnknown_QueryInterface
,
937 Test_IUnknown_AddRef
,
938 Test_IUnknown_Release
,
941 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
943 static HRESULT WINAPI
PSFactoryBuffer_QueryInterface(
944 IPSFactoryBuffer
* This
,
945 /* [in] */ REFIID riid
,
946 /* [iid_is][out] */ void **ppvObject
)
948 if (IsEqualIID(riid
, &IID_IUnknown
) ||
949 IsEqualIID(riid
, &IID_IPSFactoryBuffer
))
952 IPSFactoryBuffer_AddRef(This
);
955 return E_NOINTERFACE
;
958 static ULONG WINAPI
PSFactoryBuffer_AddRef(
959 IPSFactoryBuffer
* This
)
964 static ULONG WINAPI
PSFactoryBuffer_Release(
965 IPSFactoryBuffer
* This
)
970 static HRESULT WINAPI
PSFactoryBuffer_CreateProxy(
971 IPSFactoryBuffer
* This
,
972 /* [in] */ IUnknown
*pUnkOuter
,
973 /* [in] */ REFIID riid
,
974 /* [out] */ IRpcProxyBuffer
**ppProxy
,
975 /* [out] */ void **ppv
)
980 static HRESULT WINAPI
PSFactoryBuffer_CreateStub(
981 IPSFactoryBuffer
* This
,
982 /* [in] */ REFIID riid
,
983 /* [unique][in] */ IUnknown
*pUnkServer
,
984 /* [out] */ IRpcStubBuffer
**ppStub
)
989 static IPSFactoryBufferVtbl PSFactoryBufferVtbl
=
991 PSFactoryBuffer_QueryInterface
,
992 PSFactoryBuffer_AddRef
,
993 PSFactoryBuffer_Release
,
994 PSFactoryBuffer_CreateProxy
,
995 PSFactoryBuffer_CreateStub
998 static IPSFactoryBuffer PSFactoryBuffer
= { &PSFactoryBufferVtbl
};
1000 static const CLSID CLSID_WineTestPSFactoryBuffer
=
1005 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1006 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
1008 static void test_CoRegisterPSClsid(void)
1011 DWORD dwRegistrationKey
;
1015 hr
= CoRegisterPSClsid(&IID_IWineTest
, &CLSID_WineTestPSFactoryBuffer
);
1016 ok(hr
== CO_E_NOTINITIALIZED
, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
1018 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1020 hr
= CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer
, (IUnknown
*)&PSFactoryBuffer
,
1021 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, &dwRegistrationKey
);
1022 ok_ole_success(hr
, "CoRegisterClassObject");
1024 hr
= CoRegisterPSClsid(&IID_IWineTest
, &CLSID_WineTestPSFactoryBuffer
);
1025 ok_ole_success(hr
, "CoRegisterPSClsid");
1027 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1028 ok_ole_success(hr
, "CreateStreamOnHGlobal");
1030 hr
= CoMarshalInterface(stream
, &IID_IWineTest
, &Test_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1031 ok(hr
== E_NOTIMPL
, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr
);
1032 IStream_Release(stream
);
1034 hr
= CoRevokeClassObject(dwRegistrationKey
);
1035 ok_ole_success(hr
, "CoRevokeClassObject");
1039 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1041 hr
= CoGetPSClsid(&IID_IWineTest
, &clsid
);
1042 ok(hr
== REGDB_E_IIDNOTREG
, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr
);
1047 static void test_CoGetPSClsid(void)
1055 const BOOL is_win64
= (sizeof(void*) != sizeof(int));
1056 BOOL is_wow64
= FALSE
;
1058 hr
= CoGetPSClsid(&IID_IClassFactory
, &clsid
);
1059 ok(hr
== CO_E_NOTINITIALIZED
,
1060 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
1063 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1065 hr
= CoGetPSClsid(&IID_IClassFactory
, &clsid
);
1066 ok_ole_success(hr
, "CoGetPSClsid");
1068 hr
= CoGetPSClsid(&IID_IWineTest
, &clsid
);
1069 ok(hr
== REGDB_E_IIDNOTREG
,
1070 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
1073 hr
= CoGetPSClsid(&IID_IClassFactory
, NULL
);
1074 ok(hr
== E_INVALIDARG
,
1075 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
1078 if (!pRegOverridePredefKey
)
1080 win_skip("RegOverridePredefKey not available\n");
1084 hr
= CoGetPSClsid(&IID_IClassFactory
, &clsid
);
1085 ok_ole_success(hr
, "CoGetPSClsid");
1087 res
= RegCreateKeyExA(HKEY_CURRENT_USER
, "Software\\Classes", 0, NULL
, 0,
1088 KEY_ALL_ACCESS
, NULL
, &hkey
, NULL
);
1089 ok(!res
, "RegCreateKeyEx returned %d\n", res
);
1091 res
= pRegOverridePredefKey(HKEY_CLASSES_ROOT
, hkey
);
1092 ok(!res
, "RegOverridePredefKey returned %d\n", res
);
1094 hr
= CoGetPSClsid(&IID_IClassFactory
, &clsid
);
1095 ok_ole_success(hr
, "CoGetPSClsid");
1097 res
= pRegOverridePredefKey(HKEY_CLASSES_ROOT
, NULL
);
1098 ok(!res
, "RegOverridePredefKey returned %d\n", res
);
1102 /* not registered CLSID */
1103 hr
= CoGetPSClsid(&IID_Testiface
, &clsid
);
1104 ok(hr
== REGDB_E_IIDNOTREG
, "got 0x%08x\n", hr
);
1106 if ((handle
= activate_context(actctx_manifest
, &cookie
)))
1108 memset(&clsid
, 0, sizeof(clsid
));
1109 hr
= CoGetPSClsid(&IID_Testiface
, &clsid
);
1110 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1111 ok(IsEqualGUID(&clsid
, &IID_Testiface
), "got clsid %s\n", wine_dbgstr_guid(&clsid
));
1113 memset(&clsid
, 0, sizeof(clsid
));
1114 hr
= CoGetPSClsid(&IID_Testiface2
, &clsid
);
1115 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1116 ok(IsEqualGUID(&clsid
, &IID_Testiface2
), "got clsid %s\n", wine_dbgstr_guid(&clsid
));
1118 memset(&clsid
, 0, sizeof(clsid
));
1119 hr
= CoGetPSClsid(&IID_Testiface3
, &clsid
);
1120 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1121 ok(IsEqualGUID(&clsid
, &IID_TestPS
), "got clsid %s\n", wine_dbgstr_guid(&clsid
));
1123 memset(&clsid
, 0xaa, sizeof(clsid
));
1124 hr
= CoGetPSClsid(&IID_Testiface4
, &clsid
);
1125 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1126 ok(IsEqualGUID(&clsid
, &GUID_NULL
), "got clsid %s\n", wine_dbgstr_guid(&clsid
));
1128 /* register same interface and try to get CLSID back */
1129 hr
= CoRegisterPSClsid(&IID_Testiface
, &IID_Testiface4
);
1130 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1131 memset(&clsid
, 0, sizeof(clsid
));
1132 hr
= CoGetPSClsid(&IID_Testiface
, &clsid
);
1133 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1134 ok(IsEqualGUID(&clsid
, &IID_Testiface4
), "got clsid %s\n", wine_dbgstr_guid(&clsid
));
1136 pDeactivateActCtx(0, cookie
);
1137 pReleaseActCtx(handle
);
1140 if (pRegDeleteKeyExA
&&
1142 (pIsWow64Process
&& pIsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)))
1144 static GUID IID_DeadBeef
= {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1145 static const char clsidDeadBeef
[] = "{deadbeef-dead-beef-dead-beefdeadbeef}";
1146 static const char clsidA
[] = "{66666666-8888-7777-6666-555555555555}";
1147 HKEY hkey_iface
, hkey_psclsid
;
1148 REGSAM opposite
= is_win64
? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
;
1150 hr
= CoGetPSClsid(&IID_DeadBeef
, &clsid
);
1151 ok(hr
== REGDB_E_IIDNOTREG
, "got 0x%08x\n", hr
);
1153 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, "Interface",
1154 0, NULL
, 0, KEY_ALL_ACCESS
| opposite
, NULL
, &hkey_iface
, NULL
);
1155 ok(!res
, "RegCreateKeyEx returned %d\n", res
);
1156 res
= RegCreateKeyExA(hkey_iface
, clsidDeadBeef
,
1157 0, NULL
, 0, KEY_ALL_ACCESS
| opposite
, NULL
, &hkey
, NULL
);
1158 ok(!res
, "RegCreateKeyEx returned %d\n", res
);
1159 res
= RegCreateKeyExA(hkey
, "ProxyStubClsid32",
1160 0, NULL
, 0, KEY_ALL_ACCESS
| opposite
, NULL
, &hkey_psclsid
, NULL
);
1161 res
= RegSetValueExA(hkey_psclsid
, NULL
, 0, REG_SZ
, (const BYTE
*)clsidA
, strlen(clsidA
)+1);
1162 ok(!res
, "RegSetValueEx returned %d\n", res
);
1163 RegCloseKey(hkey_psclsid
);
1165 hr
= CoGetPSClsid(&IID_DeadBeef
, &clsid
);
1166 ok_ole_success(hr
, "CoGetPSClsid");
1167 ok(IsEqualGUID(&clsid
, &IID_TestPS
), "got clsid %s\n", wine_dbgstr_guid(&clsid
));
1169 res
= pRegDeleteKeyExA(hkey
, "ProxyStubClsid32", opposite
, 0);
1170 ok(!res
, "RegDeleteKeyEx returned %d\n", res
);
1172 res
= pRegDeleteKeyExA(hkey_iface
, clsidDeadBeef
, opposite
, 0);
1173 ok(!res
, "RegDeleteKeyEx returned %d\n", res
);
1174 RegCloseKey(hkey_iface
);
1180 /* basic test, mainly for invalid arguments. see marshal.c for more */
1181 static void test_CoUnmarshalInterface(void)
1187 hr
= CoUnmarshalInterface(NULL
, &IID_IUnknown
, (void **)&pProxy
);
1188 ok(hr
== E_INVALIDARG
, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1190 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1191 ok_ole_success(hr
, "CreateStreamOnHGlobal");
1193 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
1195 ok(hr
== CO_E_NOTINITIALIZED
, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
1197 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1199 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
1200 ok(hr
== STG_E_READFAULT
, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr
);
1204 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, NULL
);
1205 ok(hr
== E_INVALIDARG
, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1207 IStream_Release(pStream
);
1210 static void test_CoGetInterfaceAndReleaseStream(void)
1215 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1217 hr
= CoGetInterfaceAndReleaseStream(NULL
, &IID_IUnknown
, (void**)&pUnk
);
1218 ok(hr
== E_INVALIDARG
, "hr %08x\n", hr
);
1223 /* basic test, mainly for invalid arguments. see marshal.c for more */
1224 static void test_CoMarshalInterface(void)
1228 static const LARGE_INTEGER llZero
;
1230 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1232 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1233 ok_ole_success(hr
, "CreateStreamOnHGlobal");
1235 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, NULL
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1236 ok(hr
== E_INVALIDARG
, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1238 hr
= CoMarshalInterface(NULL
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1239 ok(hr
== E_INVALIDARG
, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1241 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1242 ok_ole_success(hr
, "CoMarshalInterface");
1244 /* stream not rewound */
1245 hr
= CoReleaseMarshalData(pStream
);
1246 ok(hr
== STG_E_READFAULT
, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr
);
1248 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1249 ok_ole_success(hr
, "IStream_Seek");
1251 hr
= CoReleaseMarshalData(pStream
);
1252 ok_ole_success(hr
, "CoReleaseMarshalData");
1254 IStream_Release(pStream
);
1259 static void test_CoMarshalInterThreadInterfaceInStream(void)
1263 IClassFactory
*pProxy
;
1265 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1269 hr
= CoMarshalInterThreadInterfaceInStream(&IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, NULL
);
1270 ok(hr
== E_INVALIDARG
, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1272 hr
= CoMarshalInterThreadInterfaceInStream(&IID_IUnknown
, NULL
, &pStream
);
1273 ok(hr
== E_INVALIDARG
, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1277 hr
= CoMarshalInterThreadInterfaceInStream(&IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, &pStream
);
1278 ok_ole_success(hr
, "CoMarshalInterThreadInterfaceInStream");
1280 ok_more_than_one_lock();
1282 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1283 ok_ole_success(hr
, "CoUnmarshalInterface");
1285 IClassFactory_Release(pProxy
);
1286 IStream_Release(pStream
);
1293 static void test_CoRegisterClassObject(void)
1295 ULONG_PTR ctxcookie
;
1301 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1303 /* CLSCTX_INPROC_SERVER */
1304 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1305 CLSCTX_INPROC_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
1306 ok_ole_success(hr
, "CoRegisterClassObject");
1307 hr
= CoRevokeClassObject(cookie
);
1308 ok_ole_success(hr
, "CoRevokeClassObject");
1310 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1311 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, &cookie
);
1312 ok_ole_success(hr
, "CoRegisterClassObject");
1313 hr
= CoRevokeClassObject(cookie
);
1314 ok_ole_success(hr
, "CoRevokeClassObject");
1316 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1317 CLSCTX_INPROC_SERVER
, REGCLS_MULTI_SEPARATE
, &cookie
);
1318 ok_ole_success(hr
, "CoRegisterClassObject");
1319 hr
= CoRevokeClassObject(cookie
);
1320 ok_ole_success(hr
, "CoRevokeClassObject");
1322 /* CLSCTX_LOCAL_SERVER */
1323 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1324 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
1325 ok_ole_success(hr
, "CoRegisterClassObject");
1326 hr
= CoRevokeClassObject(cookie
);
1327 ok_ole_success(hr
, "CoRevokeClassObject");
1329 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1330 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
, &cookie
);
1331 ok_ole_success(hr
, "CoRegisterClassObject");
1332 hr
= CoRevokeClassObject(cookie
);
1333 ok_ole_success(hr
, "CoRevokeClassObject");
1335 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1336 CLSCTX_LOCAL_SERVER
, REGCLS_MULTI_SEPARATE
, &cookie
);
1337 ok_ole_success(hr
, "CoRegisterClassObject");
1338 hr
= CoRevokeClassObject(cookie
);
1339 ok_ole_success(hr
, "CoRevokeClassObject");
1341 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
1342 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1343 CLSCTX_INPROC_SERVER
|CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
1344 ok_ole_success(hr
, "CoRegisterClassObject");
1345 hr
= CoRevokeClassObject(cookie
);
1346 ok_ole_success(hr
, "CoRevokeClassObject");
1348 /* test whether an object that doesn't support IClassFactory can be
1349 * registered for CLSCTX_LOCAL_SERVER */
1350 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, &Test_Unknown
,
1351 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
1352 ok_ole_success(hr
, "CoRegisterClassObject");
1353 hr
= CoRevokeClassObject(cookie
);
1354 ok_ole_success(hr
, "CoRevokeClassObject");
1356 /* test whether registered class becomes invalid when apartment is destroyed */
1357 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1358 CLSCTX_INPROC_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
1359 ok_ole_success(hr
, "CoRegisterClassObject");
1362 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1364 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
, NULL
,
1365 &IID_IClassFactory
, (void **)&pcf
);
1366 ok(hr
== REGDB_E_CLASSNOTREG
, "object registered in an apartment shouldn't accessible after it is destroyed\n");
1368 /* crashes with at least win9x DCOM! */
1370 CoRevokeClassObject(cookie
);
1372 /* test that object is accessible */
1373 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
, CLSCTX_INPROC_SERVER
,
1374 REGCLS_MULTIPLEUSE
, &cookie
);
1375 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1377 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IClassFactory
, (void**)&pcf
);
1378 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1379 IClassFactory_Release(pcf
);
1381 /* context now contains CLSID_WineOOPTest, test if registered one could still be used */
1382 if ((handle
= activate_context(actctx_manifest
, &ctxcookie
)))
1384 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IClassFactory
, (void**)&pcf
);
1386 ok(hr
== HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND
), "got 0x%08x\n", hr
);
1388 pDeactivateActCtx(0, ctxcookie
);
1389 pReleaseActCtx(handle
);
1392 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IClassFactory
, (void**)&pcf
);
1393 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1394 IClassFactory_Release(pcf
);
1396 hr
= CoRevokeClassObject(cookie
);
1397 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1402 static HRESULT
get_class_object(CLSCTX clsctx
)
1407 hr
= CoGetClassObject(&CLSID_WineOOPTest
, clsctx
, NULL
, &IID_IClassFactory
,
1411 IClassFactory_Release(pcf
);
1416 static DWORD CALLBACK
get_class_object_thread(LPVOID pv
)
1418 CLSCTX clsctx
= (CLSCTX
)(DWORD_PTR
)pv
;
1421 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1423 hr
= get_class_object(clsctx
);
1430 static DWORD CALLBACK
get_class_object_proxy_thread(LPVOID pv
)
1432 CLSCTX clsctx
= (CLSCTX
)(DWORD_PTR
)pv
;
1437 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1439 hr
= CoGetClassObject(&CLSID_WineOOPTest
, clsctx
, NULL
, &IID_IClassFactory
,
1444 hr
= IClassFactory_QueryInterface(pcf
, &IID_IMultiQI
, (void **)&pMQI
);
1446 IMultiQI_Release(pMQI
);
1447 IClassFactory_Release(pcf
);
1455 static DWORD CALLBACK
register_class_object_thread(LPVOID pv
)
1460 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1462 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1463 CLSCTX_INPROC_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
1470 static DWORD CALLBACK
revoke_class_object_thread(LPVOID pv
)
1472 DWORD cookie
= (DWORD_PTR
)pv
;
1475 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1477 hr
= CoRevokeClassObject(cookie
);
1484 static void test_registered_object_thread_affinity(void)
1492 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1494 /* CLSCTX_INPROC_SERVER */
1496 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1497 CLSCTX_INPROC_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
1498 ok_ole_success(hr
, "CoRegisterClassObject");
1500 thread
= CreateThread(NULL
, 0, get_class_object_thread
, (LPVOID
)CLSCTX_INPROC_SERVER
, 0, &tid
);
1501 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
1502 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1503 GetExitCodeThread(thread
, &exitcode
);
1505 ok(hr
== REGDB_E_CLASSNOTREG
, "CoGetClassObject on inproc object "
1506 "registered in different thread should return REGDB_E_CLASSNOTREG "
1507 "instead of 0x%08x\n", hr
);
1509 hr
= get_class_object(CLSCTX_INPROC_SERVER
);
1510 ok(hr
== S_OK
, "CoGetClassObject on inproc object registered in same "
1511 "thread should return S_OK instead of 0x%08x\n", hr
);
1513 thread
= CreateThread(NULL
, 0, register_class_object_thread
, NULL
, 0, &tid
);
1514 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
1515 ok ( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1516 GetExitCodeThread(thread
, &exitcode
);
1518 ok(hr
== S_OK
, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr
);
1520 hr
= CoRevokeClassObject(cookie
);
1521 ok_ole_success(hr
, "CoRevokeClassObject");
1523 /* CLSCTX_LOCAL_SERVER */
1525 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
1526 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
, &cookie
);
1527 ok_ole_success(hr
, "CoRegisterClassObject");
1529 thread
= CreateThread(NULL
, 0, get_class_object_proxy_thread
, (LPVOID
)CLSCTX_LOCAL_SERVER
, 0, &tid
);
1530 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
1531 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
) == WAIT_OBJECT_0
+ 1)
1534 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
1536 TranslateMessage(&msg
);
1537 DispatchMessageA(&msg
);
1540 GetExitCodeThread(thread
, &exitcode
);
1542 ok(hr
== S_OK
, "CoGetClassObject on local server object "
1543 "registered in different thread should return S_OK "
1544 "instead of 0x%08x\n", hr
);
1546 hr
= get_class_object(CLSCTX_LOCAL_SERVER
);
1547 ok(hr
== S_OK
, "CoGetClassObject on local server object registered in same "
1548 "thread should return S_OK instead of 0x%08x\n", hr
);
1550 thread
= CreateThread(NULL
, 0, revoke_class_object_thread
, (LPVOID
)(DWORD_PTR
)cookie
, 0, &tid
);
1551 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
1552 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1553 GetExitCodeThread(thread
, &exitcode
);
1555 ok(hr
== RPC_E_WRONG_THREAD
, "CoRevokeClassObject called from different "
1556 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr
);
1558 thread
= CreateThread(NULL
, 0, register_class_object_thread
, NULL
, 0, &tid
);
1559 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
1560 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1561 GetExitCodeThread(thread
, &exitcode
);
1563 ok(hr
== S_OK
, "CoRegisterClassObject with same CLSID but in different "
1564 "thread should return S_OK instead of 0x%08x\n", hr
);
1566 hr
= CoRevokeClassObject(cookie
);
1567 ok_ole_success(hr
, "CoRevokeClassObject");
1572 static DWORD CALLBACK
free_libraries_thread(LPVOID p
)
1574 CoFreeUnusedLibraries();
1578 static inline BOOL
is_module_loaded(const char *module
)
1580 return GetModuleHandleA(module
) != 0;
1583 static void test_CoFreeUnusedLibraries(void)
1590 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1592 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1594 hr
= CoCreateInstance(&CLSID_FileProtocol
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IInternetProtocol
, (void **)&pUnk
);
1595 if (hr
== REGDB_E_CLASSNOTREG
)
1597 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1601 ok_ole_success(hr
, "CoCreateInstance");
1603 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1606 broken(pUnk
== NULL
), /* win9x */
1607 "Expected a valid pointer\n");
1609 IUnknown_Release(pUnk
);
1611 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1613 thread
= CreateThread(NULL
, 0, free_libraries_thread
, NULL
, 0, &tid
);
1614 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1615 CloseHandle(thread
);
1617 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1619 CoFreeUnusedLibraries();
1621 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1626 static void test_CoGetObjectContext(void)
1630 IComThreadingInfo
*pComThreadingInfo
;
1631 IContextCallback
*pContextCallback
;
1632 IObjContext
*pObjContext
;
1637 DWORD tid
, exitcode
;
1639 if (!pCoGetObjectContext
)
1641 skip("CoGetObjectContext not present\n");
1645 hr
= pCoGetObjectContext(&IID_IComThreadingInfo
, (void **)&pComThreadingInfo
);
1646 ok(hr
== CO_E_NOTINITIALIZED
, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
1647 ok(pComThreadingInfo
== NULL
, "pComThreadingInfo should have been set to NULL\n");
1649 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1650 thread has already done so */
1652 info
.wait
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1653 ok(info
.wait
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
1655 info
.stop
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1656 ok(info
.stop
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
1658 thread
= CreateThread(NULL
, 0, ole_initialize_thread
, &info
, 0, &tid
);
1659 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
1661 ok( !WaitForSingleObject(info
.wait
, 10000), "wait timed out\n" );
1663 pComThreadingInfo
= NULL
;
1664 hr
= pCoGetObjectContext(&IID_IComThreadingInfo
, (void **)&pComThreadingInfo
);
1665 ok(hr
== S_OK
, "Expected S_OK, got 0x%08x\n", hr
);
1666 IComThreadingInfo_Release(pComThreadingInfo
);
1668 SetEvent(info
.stop
);
1669 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1671 GetExitCodeThread(thread
, &exitcode
);
1673 ok(hr
== S_OK
, "thread should have returned S_OK instead of 0x%08x\n", hr
);
1675 CloseHandle(thread
);
1676 CloseHandle(info
.wait
);
1677 CloseHandle(info
.stop
);
1679 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1681 hr
= pCoGetObjectContext(&IID_IComThreadingInfo
, (void **)&pComThreadingInfo
);
1682 ok_ole_success(hr
, "CoGetObjectContext");
1684 hr
= IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo
, &apttype
);
1685 ok_ole_success(hr
, "IComThreadingInfo_GetCurrentApartmentType");
1686 ok(apttype
== APTTYPE_MAINSTA
, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype
);
1688 hr
= IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo
, &thdtype
);
1689 ok_ole_success(hr
, "IComThreadingInfo_GetCurrentThreadType");
1690 ok(thdtype
== THDTYPE_PROCESSMESSAGES
, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype
);
1692 refs
= IComThreadingInfo_Release(pComThreadingInfo
);
1693 ok(refs
== 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs
);
1695 hr
= pCoGetObjectContext(&IID_IContextCallback
, (void **)&pContextCallback
);
1696 ok_ole_success(hr
, "CoGetObjectContext(ContextCallback)");
1700 refs
= IContextCallback_Release(pContextCallback
);
1701 ok(refs
== 0, "pContextCallback should have 0 refs instead of %d refs\n", refs
);
1706 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1708 hr
= pCoGetObjectContext(&IID_IComThreadingInfo
, (void **)&pComThreadingInfo
);
1709 ok_ole_success(hr
, "CoGetObjectContext");
1711 hr
= IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo
, &apttype
);
1712 ok_ole_success(hr
, "IComThreadingInfo_GetCurrentApartmentType");
1713 ok(apttype
== APTTYPE_MTA
, "apartment type should be APTTYPE_MTA instead of %d\n", apttype
);
1715 hr
= IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo
, &thdtype
);
1716 ok_ole_success(hr
, "IComThreadingInfo_GetCurrentThreadType");
1717 ok(thdtype
== THDTYPE_BLOCKMESSAGES
, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype
);
1719 refs
= IComThreadingInfo_Release(pComThreadingInfo
);
1720 ok(refs
== 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs
);
1722 hr
= pCoGetObjectContext(&IID_IContextCallback
, (void **)&pContextCallback
);
1723 ok_ole_success(hr
, "CoGetObjectContext(ContextCallback)");
1727 refs
= IContextCallback_Release(pContextCallback
);
1728 ok(refs
== 0, "pContextCallback should have 0 refs instead of %d refs\n", refs
);
1731 hr
= pCoGetObjectContext(&IID_IObjContext
, (void **)&pObjContext
);
1732 ok_ole_success(hr
, "CoGetObjectContext");
1734 refs
= IObjContext_Release(pObjContext
);
1735 ok(refs
== 0, "pObjContext should have 0 refs instead of %d refs\n", refs
);
1741 IUnknown IUnknown_iface
;
1745 static inline Test_CallContext
*impl_from_IUnknown(IUnknown
*iface
)
1747 return CONTAINING_RECORD(iface
, Test_CallContext
, IUnknown_iface
);
1750 static HRESULT WINAPI
Test_CallContext_QueryInterface(
1755 if (ppvObj
== NULL
) return E_POINTER
;
1757 if (IsEqualGUID(riid
, &IID_IUnknown
))
1760 IUnknown_AddRef(iface
);
1765 return E_NOINTERFACE
;
1768 static ULONG WINAPI
Test_CallContext_AddRef(IUnknown
*iface
)
1770 Test_CallContext
*This
= impl_from_IUnknown(iface
);
1771 return InterlockedIncrement(&This
->refs
);
1774 static ULONG WINAPI
Test_CallContext_Release(IUnknown
*iface
)
1776 Test_CallContext
*This
= impl_from_IUnknown(iface
);
1777 ULONG refs
= InterlockedDecrement(&This
->refs
);
1779 HeapFree(GetProcessHeap(), 0, This
);
1783 static const IUnknownVtbl TestCallContext_Vtbl
=
1785 Test_CallContext_QueryInterface
,
1786 Test_CallContext_AddRef
,
1787 Test_CallContext_Release
1790 static void test_CoGetCallContext(void)
1795 Test_CallContext
*test_object
;
1797 if (!pCoSwitchCallContext
)
1799 skip("CoSwitchCallContext not present\n");
1805 test_object
= HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext
));
1806 test_object
->IUnknown_iface
.lpVtbl
= &TestCallContext_Vtbl
;
1807 test_object
->refs
= 1;
1809 hr
= CoGetCallContext(&IID_IUnknown
, (void**)&pUnk
);
1810 ok(hr
== RPC_E_CALL_COMPLETE
, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr
);
1812 pUnk
= (IUnknown
*)0xdeadbeef;
1813 hr
= pCoSwitchCallContext(&test_object
->IUnknown_iface
, &pUnk
);
1814 ok_ole_success(hr
, "CoSwitchCallContext");
1815 ok(pUnk
== NULL
, "expected NULL, got %p\n", pUnk
);
1816 refs
= IUnknown_AddRef(&test_object
->IUnknown_iface
);
1817 ok(refs
== 2, "Expected refcount 2, got %d\n", refs
);
1818 IUnknown_Release(&test_object
->IUnknown_iface
);
1820 pUnk
= (IUnknown
*)0xdeadbeef;
1821 hr
= CoGetCallContext(&IID_IUnknown
, (void**)&pUnk
);
1822 ok_ole_success(hr
, "CoGetCallContext");
1823 ok(pUnk
== &test_object
->IUnknown_iface
, "expected %p, got %p\n",
1824 &test_object
->IUnknown_iface
, pUnk
);
1825 refs
= IUnknown_AddRef(&test_object
->IUnknown_iface
);
1826 ok(refs
== 3, "Expected refcount 3, got %d\n", refs
);
1827 IUnknown_Release(&test_object
->IUnknown_iface
);
1828 IUnknown_Release(pUnk
);
1830 pUnk
= (IUnknown
*)0xdeadbeef;
1831 hr
= pCoSwitchCallContext(NULL
, &pUnk
);
1832 ok_ole_success(hr
, "CoSwitchCallContext");
1833 ok(pUnk
== &test_object
->IUnknown_iface
, "expected %p, got %p\n",
1834 &test_object
->IUnknown_iface
, pUnk
);
1835 refs
= IUnknown_AddRef(&test_object
->IUnknown_iface
);
1836 ok(refs
== 2, "Expected refcount 2, got %d\n", refs
);
1837 IUnknown_Release(&test_object
->IUnknown_iface
);
1839 hr
= CoGetCallContext(&IID_IUnknown
, (void**)&pUnk
);
1840 ok(hr
== RPC_E_CALL_COMPLETE
, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr
);
1842 IUnknown_Release(&test_object
->IUnknown_iface
);
1847 static void test_CoGetContextToken(void)
1855 DWORD tid
, exitcode
;
1857 if (!pCoGetContextToken
)
1859 win_skip("CoGetContextToken not present\n");
1864 hr
= pCoGetContextToken(&token
);
1865 ok(hr
== CO_E_NOTINITIALIZED
, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr
);
1866 ok(token
== 0xdeadbeef, "Expected 0, got 0x%lx\n", token
);
1868 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1869 thread has already done so */
1871 info
.wait
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1872 ok(info
.wait
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
1874 info
.stop
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1875 ok(info
.stop
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
1877 thread
= CreateThread(NULL
, 0, ole_initialize_thread
, &info
, 0, &tid
);
1878 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
1880 ok( !WaitForSingleObject(info
.wait
, 10000), "wait timed out\n" );
1883 hr
= pCoGetContextToken(&token
);
1884 ok(hr
== S_OK
, "Expected S_OK, got 0x%08x\n", hr
);
1886 SetEvent(info
.stop
);
1887 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1889 GetExitCodeThread(thread
, &exitcode
);
1891 ok(hr
== S_OK
, "thread should have returned S_OK instead of 0x%08x\n", hr
);
1893 CloseHandle(thread
);
1894 CloseHandle(info
.wait
);
1895 CloseHandle(info
.stop
);
1899 hr
= pCoGetContextToken(NULL
);
1900 ok(hr
== E_POINTER
, "Expected E_POINTER, got 0x%08x\n", hr
);
1903 hr
= pCoGetContextToken(&token
);
1904 ok(hr
== S_OK
, "Expected S_OK, got 0x%08x\n", hr
);
1905 ok(token
, "Expected token != 0\n");
1907 refs
= IUnknown_AddRef((IUnknown
*)token
);
1908 todo_wine
ok(refs
== 1, "Expected 1, got %u\n", refs
);
1910 hr
= pCoGetObjectContext(&IID_IObjContext
, (void **)&ctx
);
1911 ok(hr
== S_OK
, "Expected S_OK, got 0x%08x\n", hr
);
1912 todo_wine
ok(ctx
== (IObjContext
*)token
, "Expected interface pointers to be the same\n");
1914 refs
= IObjContext_AddRef(ctx
);
1915 todo_wine
ok(refs
== 3, "Expected 3, got %u\n", refs
);
1917 refs
= IObjContext_Release(ctx
);
1918 todo_wine
ok(refs
== 2, "Expected 2, got %u\n", refs
);
1920 refs
= IUnknown_Release((IUnknown
*)token
);
1921 ok(refs
== 1, "Expected 1, got %u\n", refs
);
1923 /* CoGetContextToken does not add a reference */
1925 hr
= pCoGetContextToken(&token
);
1926 ok(hr
== S_OK
, "Expected S_OK, got 0x%08x\n", hr
);
1927 ok(token
, "Expected token != 0\n");
1928 todo_wine
ok(ctx
== (IObjContext
*)token
, "Expected interface pointers to be the same\n");
1930 refs
= IObjContext_AddRef(ctx
);
1931 ok(refs
== 2, "Expected 1, got %u\n", refs
);
1933 refs
= IObjContext_Release(ctx
);
1934 ok(refs
== 1, "Expected 0, got %u\n", refs
);
1936 refs
= IObjContext_Release(ctx
);
1937 ok(refs
== 0, "Expected 0, got %u\n", refs
);
1942 static void test_TreatAsClass(void)
1946 static GUID deadbeef
= {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1947 static const char deadbeefA
[] = "{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}";
1948 IInternetProtocol
*pIP
= NULL
;
1949 HKEY clsidkey
, deadbeefkey
;
1952 if (!pCoGetTreatAsClass
)
1954 win_skip("CoGetTreatAsClass not present\n");
1957 hr
= pCoGetTreatAsClass(&deadbeef
,&out
);
1958 ok (hr
== S_FALSE
, "expected S_FALSE got %x\n",hr
);
1959 ok (IsEqualGUID(&out
,&deadbeef
), "expected to get same clsid back\n");
1961 lr
= RegOpenKeyExA(HKEY_CLASSES_ROOT
, "CLSID", 0, KEY_READ
, &clsidkey
);
1962 ok(lr
== ERROR_SUCCESS
, "Couldn't open CLSID key\n");
1964 lr
= RegCreateKeyExA(clsidkey
, deadbeefA
, 0, NULL
, 0, KEY_WRITE
, NULL
, &deadbeefkey
, NULL
);
1965 ok(lr
== ERROR_SUCCESS
, "Couldn't create class key\n");
1967 hr
= pCoTreatAsClass(&deadbeef
, &deadbeef
);
1968 ok(hr
== REGDB_E_WRITEREGDB
, "CoTreatAsClass gave wrong error: %08x\n", hr
);
1970 hr
= pCoTreatAsClass(&deadbeef
, &CLSID_FileProtocol
);
1971 if(hr
== REGDB_E_WRITEREGDB
){
1972 win_skip("Insufficient privileges to use CoTreatAsClass\n");
1975 ok(hr
== S_OK
, "CoTreatAsClass failed: %08x\n", hr
);
1977 hr
= pCoGetTreatAsClass(&deadbeef
, &out
);
1978 ok(hr
== S_OK
, "CoGetTreatAsClass failed: %08x\n",hr
);
1979 ok(IsEqualGUID(&out
, &CLSID_FileProtocol
), "expected to get substituted clsid\n");
1981 OleInitialize(NULL
);
1983 hr
= CoCreateInstance(&deadbeef
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IInternetProtocol
, (void **)&pIP
);
1984 if(hr
== REGDB_E_CLASSNOTREG
)
1986 win_skip("IE not installed so can't test CoCreateInstance\n");
1990 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
1992 IInternetProtocol_Release(pIP
);
1996 hr
= pCoTreatAsClass(&deadbeef
, &CLSID_NULL
);
1997 ok(hr
== S_OK
, "CoTreatAsClass failed: %08x\n", hr
);
1999 hr
= pCoGetTreatAsClass(&deadbeef
, &out
);
2000 ok(hr
== S_FALSE
, "expected S_FALSE got %08x\n", hr
);
2001 ok(IsEqualGUID(&out
, &deadbeef
), "expected to get same clsid back\n");
2003 /* bizarrely, native's CoTreatAsClass takes some time to take effect in CoCreateInstance */
2006 hr
= CoCreateInstance(&deadbeef
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IInternetProtocol
, (void **)&pIP
);
2007 ok(hr
== REGDB_E_CLASSNOTREG
, "CoCreateInstance gave wrong error: %08x\n", hr
);
2010 IInternetProtocol_Release(pIP
);
2014 RegCloseKey(deadbeefkey
);
2015 RegDeleteKeyA(clsidkey
, deadbeefA
);
2016 RegCloseKey(clsidkey
);
2019 static void test_CoInitializeEx(void)
2023 hr
= pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2024 ok(hr
== S_OK
, "CoInitializeEx failed with error 0x%08x\n", hr
);
2026 /* Calling OleInitialize for the first time should yield S_OK even with
2027 * apartment already initialized by previous CoInitialize(Ex) calls. */
2028 hr
= OleInitialize(NULL
);
2029 ok(hr
== S_OK
, "OleInitialize failed with error 0x%08x\n", hr
);
2031 /* Subsequent calls to OleInitialize should return S_FALSE */
2032 hr
= OleInitialize(NULL
);
2033 ok(hr
== S_FALSE
, "Expected S_FALSE, hr = 0x%08x\n", hr
);
2041 static void test_OleRegGetMiscStatus(void)
2048 hr
= OleRegGetMiscStatus(&CLSID_Testclass
, DVASPECT_ICON
, NULL
);
2049 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2051 status
= 0xdeadbeef;
2052 hr
= OleRegGetMiscStatus(&CLSID_Testclass
, DVASPECT_ICON
, &status
);
2053 ok(hr
== REGDB_E_CLASSNOTREG
, "got 0x%08x\n", hr
);
2054 ok(status
== 0, "got 0x%08x\n", status
);
2057 hr
= OleRegGetMiscStatus(&CLSID_StdFont
, DVASPECT_ICON
, &status
);
2058 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2059 ok(status
== 0, "got 0x%08x\n", status
);
2061 if ((handle
= activate_context(actctx_manifest
, &cookie
)))
2064 hr
= OleRegGetMiscStatus(&CLSID_Testclass
, DVASPECT_ICON
, &status
);
2065 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2066 ok(status
== OLEMISC_RECOMPOSEONRESIZE
, "got 0x%08x\n", status
);
2068 /* context data takes precedence over registration info */
2070 hr
= OleRegGetMiscStatus(&CLSID_StdFont
, DVASPECT_ICON
, &status
);
2071 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2072 ok(status
== OLEMISC_RECOMPOSEONRESIZE
, "got 0x%08x\n", status
);
2074 /* there's no such attribute in context */
2076 hr
= OleRegGetMiscStatus(&CLSID_Testclass
, DVASPECT_DOCPRINT
, &status
);
2077 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2078 ok(status
== 0, "got 0x%08x\n", status
);
2080 pDeactivateActCtx(0, cookie
);
2081 pReleaseActCtx(handle
);
2085 static void test_CoCreateGuid(void)
2089 hr
= CoCreateGuid(NULL
);
2090 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
2093 static void CALLBACK
apc_test_proc(ULONG_PTR param
)
2098 static DWORD CALLBACK
release_semaphore_thread( LPVOID arg
)
2100 HANDLE handle
= arg
;
2101 if (WaitForSingleObject(handle
, 200) == WAIT_TIMEOUT
)
2102 ReleaseSemaphore(handle
, 1, NULL
);
2106 static void test_CoWaitForMultipleHandles(void)
2108 static const char cls_name
[] = "cowait_test_class";
2109 HANDLE handles
[2], thread
;
2117 hr
= pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2118 ok(hr
== S_OK
, "CoInitializeEx failed with error 0x%08x\n", hr
);
2120 memset(&wc
, 0, sizeof(wc
));
2121 wc
.cbSize
= sizeof(wc
);
2122 wc
.style
= CS_VREDRAW
| CS_HREDRAW
;
2123 wc
.hInstance
= GetModuleHandleA(0);
2124 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
2125 wc
.hbrBackground
= NULL
;
2126 wc
.lpszClassName
= cls_name
;
2127 wc
.lpfnWndProc
= DefWindowProcA
;
2128 success
= RegisterClassExA(&wc
) != 0;
2129 ok(success
, "RegisterClassExA failed %u\n", GetLastError());
2131 hWnd
= CreateWindowExA(0, cls_name
, "Test", WS_TILEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
2132 ok(hWnd
!= 0, "CreateWindowExA failed %u\n", GetLastError());
2133 handles
[0] = CreateSemaphoreA(NULL
, 1, 1, NULL
);
2134 ok(handles
[0] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2135 handles
[1] = CreateSemaphoreA(NULL
, 1, 1, NULL
);
2136 ok(handles
[1] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2138 /* test without flags */
2140 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2141 hr
= CoWaitForMultipleHandles(0, 50, 0, handles
, NULL
);
2143 ok(hr
== E_INVALIDARG
, "expected E_INVALIDARG, got 0x%08x\n", hr
);
2144 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2146 ok(success
, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2149 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2150 hr
= CoWaitForMultipleHandles(0, 50, 0, NULL
, &index
);
2152 ok(hr
== E_INVALIDARG
, "expected E_INVALIDARG, got 0x%08x\n", hr
);
2154 ok(index
== 0, "expected index 0, got %u\n", index
);
2155 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2157 ok(success
, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2160 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2161 hr
= CoWaitForMultipleHandles(0, 50, 0, handles
, &index
);
2163 ok(hr
== RPC_E_NO_SYNC
, "expected RPC_E_NO_SYNC, got 0x%08x\n", hr
);
2165 ok(index
== 0, "expected index 0, got %u\n", index
);
2166 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2168 ok(success
, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2171 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2172 hr
= CoWaitForMultipleHandles(0, 50, 1, handles
, &index
);
2173 ok(hr
== S_OK
, "expected S_OK, got 0x%08x\n", hr
);
2174 ok(index
== 0, "expected index 0, got %u\n", index
);
2175 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2176 ok(success
, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2179 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2180 hr
= CoWaitForMultipleHandles(0, 50, 2, handles
, &index
);
2181 ok(hr
== S_OK
, "expected S_OK, got 0x%08x\n", hr
);
2182 ok(index
== 1, "expected index 1, got %u\n", index
);
2183 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2184 ok(success
, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2187 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2188 hr
= CoWaitForMultipleHandles(0, 50, 2, handles
, &index
);
2189 ok(hr
== RPC_S_CALLPENDING
, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr
);
2191 ok(index
== 0 || broken(index
== 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index
);
2192 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2193 ok(!success
, "CoWaitForMultipleHandles didn't pump any messages\n");
2195 ReleaseSemaphore(handles
[0], 1, NULL
);
2196 ReleaseSemaphore(handles
[1], 1, NULL
);
2198 /* test with COWAIT_WAITALL */
2201 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2202 hr
= CoWaitForMultipleHandles(COWAIT_WAITALL
, 50, 2, handles
, &index
);
2203 ok(hr
== S_OK
, "expected S_OK, got 0x%08x\n", hr
);
2204 ok(index
== 0, "expected index 0, got %u\n", index
);
2205 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2206 ok(success
, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2209 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2210 hr
= CoWaitForMultipleHandles(0, 50, 2, handles
, &index
);
2211 ok(hr
== RPC_S_CALLPENDING
, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr
);
2213 ok(index
== 0 || broken(index
== 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index
);
2214 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2215 ok(!success
, "CoWaitForMultipleHandles didn't pump any messages\n");
2217 ReleaseSemaphore(handles
[0], 1, NULL
);
2218 ReleaseSemaphore(handles
[1], 1, NULL
);
2220 /* test with COWAIT_ALERTABLE */
2223 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2224 hr
= CoWaitForMultipleHandles(COWAIT_ALERTABLE
, 50, 1, handles
, &index
);
2225 ok(hr
== S_OK
, "expected S_OK, got 0x%08x\n", hr
);
2226 ok(index
== 0, "expected index 0, got %u\n", index
);
2227 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2228 ok(success
, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2231 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2232 hr
= CoWaitForMultipleHandles(COWAIT_ALERTABLE
, 50, 2, handles
, &index
);
2233 ok(hr
== S_OK
, "expected S_OK, got 0x%08x\n", hr
);
2234 ok(index
== 1, "expected index 1, got %u\n", index
);
2235 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2236 ok(success
, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2239 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2240 hr
= CoWaitForMultipleHandles(COWAIT_ALERTABLE
, 50, 2, handles
, &index
);
2241 ok(hr
== RPC_S_CALLPENDING
, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr
);
2243 ok(index
== 0 || broken(index
== 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index
);
2244 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2245 ok(!success
, "CoWaitForMultipleHandles didn't pump any messages\n");
2248 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2249 success
= QueueUserAPC(apc_test_proc
, GetCurrentThread(), 0);
2250 ok(success
, "QueueUserAPC failed %u\n", GetLastError());
2251 hr
= CoWaitForMultipleHandles(COWAIT_ALERTABLE
, 50, 2, handles
, &index
);
2252 ok(hr
== S_OK
, "expected S_OK, got 0x%08x\n", hr
);
2253 ok(index
== WAIT_IO_COMPLETION
, "expected index WAIT_IO_COMPLETION, got %u\n", index
);
2254 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2256 ok(success
, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2258 /* test with COWAIT_INPUTAVAILABLE (semaphores are still locked) */
2261 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2262 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_NOREMOVE
);
2263 ok(success
, "PeekMessageA returned FALSE\n");
2264 hr
= CoWaitForMultipleHandles(0, 50, 2, handles
, &index
);
2265 ok(hr
== RPC_S_CALLPENDING
, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr
);
2267 ok(index
== 0 || broken(index
== 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index
);
2268 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2269 ok(!success
, "CoWaitForMultipleHandles didn't pump any messages\n");
2272 PostMessageA(hWnd
, WM_DDE_FIRST
, 0, 0);
2273 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_NOREMOVE
);
2274 ok(success
, "PeekMessageA returned FALSE\n");
2275 thread
= CreateThread(NULL
, 0, release_semaphore_thread
, handles
[1], 0, &tid
);
2276 ok(thread
!= NULL
, "CreateThread failed, error %u\n", GetLastError());
2277 hr
= CoWaitForMultipleHandles(COWAIT_INPUTAVAILABLE
, 50, 2, handles
, &index
);
2278 ok(hr
== RPC_S_CALLPENDING
|| broken(hr
== E_INVALIDARG
) || broken(hr
== S_OK
) /* Win 8 */,
2279 "expected RPC_S_CALLPENDING, got 0x%08x\n", hr
);
2280 ReleaseSemaphore(handles
[1], 1, NULL
);
2282 ok(index
== 0 || broken(index
== 1) /* Win 8 */, "expected index 0, got %u\n", index
);
2283 success
= PeekMessageA(&msg
, hWnd
, WM_DDE_FIRST
, WM_DDE_FIRST
, PM_REMOVE
);
2284 ok(!success
|| broken(success
&& hr
== E_INVALIDARG
),
2285 "CoWaitForMultipleHandles didn't pump any messages\n");
2286 index
= WaitForSingleObject(thread
, 200);
2287 ok(index
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
2288 CloseHandle(thread
);
2290 CloseHandle(handles
[0]);
2291 CloseHandle(handles
[1]);
2292 DestroyWindow(hWnd
);
2294 success
= UnregisterClassA(cls_name
, GetModuleHandleA(0));
2295 ok(success
, "UnregisterClass failed %u\n", GetLastError());
2300 static void init_funcs(void)
2302 HMODULE hOle32
= GetModuleHandleA("ole32");
2303 HMODULE hAdvapi32
= GetModuleHandleA("advapi32");
2304 HMODULE hkernel32
= GetModuleHandleA("kernel32");
2306 pCoGetObjectContext
= (void*)GetProcAddress(hOle32
, "CoGetObjectContext");
2307 pCoSwitchCallContext
= (void*)GetProcAddress(hOle32
, "CoSwitchCallContext");
2308 pCoGetTreatAsClass
= (void*)GetProcAddress(hOle32
,"CoGetTreatAsClass");
2309 pCoTreatAsClass
= (void*)GetProcAddress(hOle32
,"CoTreatAsClass");
2310 pCoGetContextToken
= (void*)GetProcAddress(hOle32
, "CoGetContextToken");
2311 pRegDeleteKeyExA
= (void*)GetProcAddress(hAdvapi32
, "RegDeleteKeyExA");
2312 pRegOverridePredefKey
= (void*)GetProcAddress(hAdvapi32
, "RegOverridePredefKey");
2313 pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx");
2315 pActivateActCtx
= (void*)GetProcAddress(hkernel32
, "ActivateActCtx");
2316 pCreateActCtxW
= (void*)GetProcAddress(hkernel32
, "CreateActCtxW");
2317 pDeactivateActCtx
= (void*)GetProcAddress(hkernel32
, "DeactivateActCtx");
2318 pIsWow64Process
= (void*)GetProcAddress(hkernel32
, "IsWow64Process");
2319 pReleaseActCtx
= (void*)GetProcAddress(hkernel32
, "ReleaseActCtx");
2326 if (!pCoInitializeEx
)
2328 trace("You need DCOM95 installed to run this test\n");
2332 if (!pCreateActCtxW
)
2333 win_skip("Activation contexts are not supported, some tests will be skipped.\n");
2335 test_ProgIDFromCLSID();
2336 test_CLSIDFromProgID();
2337 test_CLSIDFromString();
2338 test_IIDFromString();
2339 test_StringFromGUID2();
2340 test_CoCreateInstance();
2342 test_CoGetClassObject();
2343 test_CoRegisterMessageFilter();
2344 test_CoRegisterPSClsid();
2345 test_CoGetPSClsid();
2346 test_CoUnmarshalInterface();
2347 test_CoGetInterfaceAndReleaseStream();
2348 test_CoMarshalInterface();
2349 test_CoMarshalInterThreadInterfaceInStream();
2350 test_CoRegisterClassObject();
2351 test_registered_object_thread_affinity();
2352 test_CoFreeUnusedLibraries();
2353 test_CoGetObjectContext();
2354 test_CoGetCallContext();
2355 test_CoGetContextToken();
2356 test_TreatAsClass();
2357 test_CoInitializeEx();
2358 test_OleRegGetMiscStatus();
2359 test_CoCreateGuid();
2360 test_CoWaitForMultipleHandles();