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