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