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 todo_wine ok(0, "unexpected call\n"); 845 return PENDINGMSG_WAITNOPROCESS; 846 } 847 848 static const IMessageFilterVtbl MessageFilter_Vtbl = 849 { 850 MessageFilter_QueryInterface, 851 MessageFilter_AddRef, 852 MessageFilter_Release, 853 MessageFilter_HandleInComingCall, 854 MessageFilter_RetryRejectedCall, 855 MessageFilter_MessagePending 856 }; 857 858 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl }; 859 860 static void test_CoRegisterMessageFilter(void) 861 { 862 HRESULT hr; 863 IMessageFilter *prev_filter; 864 865 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter); 866 ok(hr == CO_E_NOT_SUPPORTED, 867 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n", 868 hr); 869 870 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 871 prev_filter = (IMessageFilter *)0xdeadbeef; 872 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter); 873 ok(hr == CO_E_NOT_SUPPORTED, 874 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n", 875 hr); 876 ok(prev_filter == (IMessageFilter *)0xdeadbeef, 877 "prev_filter should have been set to %p\n", prev_filter); 878 CoUninitialize(); 879 880 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 881 882 hr = CoRegisterMessageFilter(NULL, NULL); 883 ok_ole_success(hr, "CoRegisterMessageFilter"); 884 885 prev_filter = (IMessageFilter *)0xdeadbeef; 886 hr = CoRegisterMessageFilter(NULL, &prev_filter); 887 ok_ole_success(hr, "CoRegisterMessageFilter"); 888 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter); 889 890 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter); 891 ok_ole_success(hr, "CoRegisterMessageFilter"); 892 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter); 893 894 hr = CoRegisterMessageFilter(NULL, NULL); 895 ok_ole_success(hr, "CoRegisterMessageFilter"); 896 897 CoUninitialize(); 898 } 899 900 static IUnknown Test_Unknown; 901 902 static HRESULT WINAPI EnumOLEVERB_QueryInterface(IEnumOLEVERB *iface, REFIID riid, void **ppv) 903 { 904 return IUnknown_QueryInterface(&Test_Unknown, riid, ppv); 905 } 906 907 static ULONG WINAPI EnumOLEVERB_AddRef(IEnumOLEVERB *iface) 908 { 909 return 2; 910 } 911 912 static ULONG WINAPI EnumOLEVERB_Release(IEnumOLEVERB *iface) 913 { 914 return 1; 915 } 916 917 static HRESULT WINAPI EnumOLEVERB_Next(IEnumOLEVERB *iface, ULONG celt, OLEVERB *rgelt, ULONG *fetched) 918 { 919 ok(0, "unexpected call\n"); 920 return E_NOTIMPL; 921 } 922 923 static HRESULT WINAPI EnumOLEVERB_Skip(IEnumOLEVERB *iface, ULONG celt) 924 { 925 ok(0, "unexpected call\n"); 926 return E_NOTIMPL; 927 } 928 929 static HRESULT WINAPI EnumOLEVERB_Reset(IEnumOLEVERB *iface) 930 { 931 ok(0, "unexpected call\n"); 932 return E_NOTIMPL; 933 } 934 935 static HRESULT WINAPI EnumOLEVERB_Clone(IEnumOLEVERB *iface, IEnumOLEVERB **ppenum) 936 { 937 ok(0, "unexpected call\n"); 938 return E_NOTIMPL; 939 } 940 941 static const IEnumOLEVERBVtbl EnumOLEVERBVtbl = { 942 EnumOLEVERB_QueryInterface, 943 EnumOLEVERB_AddRef, 944 EnumOLEVERB_Release, 945 EnumOLEVERB_Next, 946 EnumOLEVERB_Skip, 947 EnumOLEVERB_Reset, 948 EnumOLEVERB_Clone 949 }; 950 951 static IEnumOLEVERB EnumOLEVERB = { &EnumOLEVERBVtbl }; 952 953 static HRESULT WINAPI Test_IUnknown_QueryInterface( 954 IUnknown *iface, 955 REFIID riid, 956 LPVOID *ppvObj) 957 { 958 if (ppvObj == NULL) return E_POINTER; 959 960 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IWineTest)) { 961 *ppvObj = iface; 962 }else if(IsEqualIID(riid, &IID_IEnumOLEVERB)) { 963 *ppvObj = &EnumOLEVERB; 964 }else { 965 *ppvObj = NULL; 966 return E_NOINTERFACE; 967 } 968 969 IUnknown_AddRef((IUnknown*)*ppvObj); 970 return S_OK; 971 } 972 973 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface) 974 { 975 return 2; /* non-heap-based object */ 976 } 977 978 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface) 979 { 980 return 1; /* non-heap-based object */ 981 } 982 983 static const IUnknownVtbl TestUnknown_Vtbl = 984 { 985 Test_IUnknown_QueryInterface, 986 Test_IUnknown_AddRef, 987 Test_IUnknown_Release, 988 }; 989 990 static IUnknown Test_Unknown = { &TestUnknown_Vtbl }; 991 992 static IPSFactoryBuffer *ps_factory_buffer; 993 994 static HRESULT WINAPI PSFactoryBuffer_QueryInterface( 995 IPSFactoryBuffer * This, 996 /* [in] */ REFIID riid, 997 /* [iid_is][out] */ void **ppvObject) 998 { 999 if (IsEqualIID(riid, &IID_IUnknown) || 1000 IsEqualIID(riid, &IID_IPSFactoryBuffer)) 1001 { 1002 *ppvObject = This; 1003 IPSFactoryBuffer_AddRef(This); 1004 return S_OK; 1005 } 1006 return E_NOINTERFACE; 1007 } 1008 1009 static ULONG WINAPI PSFactoryBuffer_AddRef( 1010 IPSFactoryBuffer * This) 1011 { 1012 return 2; 1013 } 1014 1015 static ULONG WINAPI PSFactoryBuffer_Release( 1016 IPSFactoryBuffer * This) 1017 { 1018 return 1; 1019 } 1020 1021 static HRESULT WINAPI PSFactoryBuffer_CreateProxy( 1022 IPSFactoryBuffer * This, 1023 /* [in] */ IUnknown *pUnkOuter, 1024 /* [in] */ REFIID riid, 1025 /* [out] */ IRpcProxyBuffer **ppProxy, 1026 /* [out] */ void **ppv) 1027 { 1028 return E_NOTIMPL; 1029 } 1030 1031 static HRESULT WINAPI PSFactoryBuffer_CreateStub( 1032 IPSFactoryBuffer * This, 1033 /* [in] */ REFIID riid, 1034 /* [unique][in] */ IUnknown *pUnkServer, 1035 /* [out] */ IRpcStubBuffer **ppStub) 1036 { 1037 CHECK_EXPECT(CreateStub); 1038 1039 ok(pUnkServer == &Test_Unknown, "unexpected pUnkServer %p\n", pUnkServer); 1040 if(!ps_factory_buffer) 1041 return E_NOTIMPL; 1042 1043 return IPSFactoryBuffer_CreateStub(ps_factory_buffer, &IID_IEnumOLEVERB, pUnkServer, ppStub); 1044 } 1045 1046 static IPSFactoryBufferVtbl PSFactoryBufferVtbl = 1047 { 1048 PSFactoryBuffer_QueryInterface, 1049 PSFactoryBuffer_AddRef, 1050 PSFactoryBuffer_Release, 1051 PSFactoryBuffer_CreateProxy, 1052 PSFactoryBuffer_CreateStub 1053 }; 1054 1055 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl }; 1056 1057 static const CLSID CLSID_WineTestPSFactoryBuffer = 1058 { 1059 0x52011640, 1060 0x8164, 1061 0x4fd0, 1062 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} 1063 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */ 1064 1065 static DWORD CALLBACK register_ps_clsid_thread(void *context) 1066 { 1067 HRESULT hr; 1068 CLSID clsid = {0}; 1069 1070 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1071 1072 hr = CoGetPSClsid(&IID_IWineTest, &clsid); 1073 ok_ole_success(hr, "CoGetPSClsid"); 1074 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n", 1075 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid)); 1076 1077 /* test registering a PSClsid in an apartment which is then destroyed */ 1078 hr = CoRegisterPSClsid(&IID_TestPS, &clsid); 1079 ok_ole_success(hr, "CoRegisterPSClsid"); 1080 1081 CoUninitialize(); 1082 1083 return hr; 1084 } 1085 1086 static void test_CoRegisterPSClsid(void) 1087 { 1088 HRESULT hr; 1089 DWORD dwRegistrationKey; 1090 IStream *stream; 1091 CLSID clsid; 1092 HANDLE thread; 1093 DWORD tid; 1094 1095 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer); 1096 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr); 1097 1098 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1099 1100 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer, 1101 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey); 1102 ok_ole_success(hr, "CoRegisterClassObject"); 1103 1104 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer); 1105 ok_ole_success(hr, "CoRegisterPSClsid"); 1106 1107 hr = CoGetPSClsid(&IID_IWineTest, &clsid); 1108 ok_ole_success(hr, "CoGetPSClsid"); 1109 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n", 1110 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid)); 1111 1112 thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid); 1113 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); 1114 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n"); 1115 CloseHandle(thread); 1116 1117 hr = CoGetPSClsid(&IID_TestPS, &clsid); 1118 ok_ole_success(hr, "CoGetPSClsid"); 1119 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n", 1120 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid)); 1121 1122 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1123 ok_ole_success(hr, "CreateStreamOnHGlobal"); 1124 1125 SET_EXPECT(CreateStub); 1126 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1127 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr); 1128 CHECK_CALLED(CreateStub, 1); 1129 1130 hr = CoGetPSClsid(&IID_IEnumOLEVERB, &clsid); 1131 ok_ole_success(hr, "CoGetPSClsid"); 1132 1133 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void **)&ps_factory_buffer); 1134 ok_ole_success(hr, "CoGetClassObject"); 1135 1136 hr = CoRegisterPSClsid(&IID_IEnumOLEVERB, &CLSID_WineTestPSFactoryBuffer); 1137 ok_ole_success(hr, "CoRegisterPSClsid"); 1138 1139 SET_EXPECT(CreateStub); 1140 hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1141 ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr); 1142 CHECK_CALLED(CreateStub, 1); 1143 1144 hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1145 ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr); 1146 1147 IStream_Release(stream); 1148 IPSFactoryBuffer_Release(ps_factory_buffer); 1149 ps_factory_buffer = NULL; 1150 1151 hr = CoRevokeClassObject(dwRegistrationKey); 1152 ok_ole_success(hr, "CoRevokeClassObject"); 1153 1154 CoUninitialize(); 1155 1156 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1157 1158 hr = CoGetPSClsid(&IID_IWineTest, &clsid); 1159 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr); 1160 1161 hr = CoGetPSClsid(&IID_TestPS, &clsid); 1162 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr); 1163 1164 CoUninitialize(); 1165 1166 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 1167 1168 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer); 1169 ok_ole_success(hr, "CoRegisterPSClsid"); 1170 1171 hr = CoGetPSClsid(&IID_IWineTest, &clsid); 1172 ok_ole_success(hr, "CoGetPSClsid"); 1173 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n", 1174 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid)); 1175 1176 thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid); 1177 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); 1178 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n"); 1179 CloseHandle(thread); 1180 1181 hr = CoGetPSClsid(&IID_TestPS, &clsid); 1182 ok_ole_success(hr, "CoGetPSClsid"); 1183 ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n", 1184 wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid)); 1185 1186 CoUninitialize(); 1187 } 1188 1189 static void test_CoGetPSClsid(void) 1190 { 1191 ULONG_PTR cookie; 1192 HANDLE handle; 1193 HRESULT hr; 1194 CLSID clsid; 1195 HKEY hkey; 1196 LONG res; 1197 const BOOL is_win64 = (sizeof(void*) != sizeof(int)); 1198 BOOL is_wow64 = FALSE; 1199 1200 hr = CoGetPSClsid(&IID_IClassFactory, &clsid); 1201 ok(hr == CO_E_NOTINITIALIZED, 1202 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", 1203 hr); 1204 1205 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1206 1207 hr = CoGetPSClsid(&IID_IClassFactory, &clsid); 1208 ok_ole_success(hr, "CoGetPSClsid"); 1209 1210 hr = CoGetPSClsid(&IID_IWineTest, &clsid); 1211 ok(hr == REGDB_E_IIDNOTREG, 1212 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n", 1213 hr); 1214 1215 hr = CoGetPSClsid(&IID_IClassFactory, NULL); 1216 ok(hr == E_INVALIDARG, 1217 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n", 1218 hr); 1219 1220 if (!pRegOverridePredefKey) 1221 { 1222 win_skip("RegOverridePredefKey not available\n"); 1223 CoUninitialize(); 1224 return; 1225 } 1226 hr = CoGetPSClsid(&IID_IClassFactory, &clsid); 1227 ok_ole_success(hr, "CoGetPSClsid"); 1228 1229 res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0, 1230 KEY_ALL_ACCESS, NULL, &hkey, NULL); 1231 ok(!res, "RegCreateKeyEx returned %d\n", res); 1232 1233 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey); 1234 ok(!res, "RegOverridePredefKey returned %d\n", res); 1235 1236 hr = CoGetPSClsid(&IID_IClassFactory, &clsid); 1237 ok_ole_success(hr, "CoGetPSClsid"); 1238 1239 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL); 1240 ok(!res, "RegOverridePredefKey returned %d\n", res); 1241 1242 RegCloseKey(hkey); 1243 1244 /* not registered CLSID */ 1245 hr = CoGetPSClsid(&IID_Testiface, &clsid); 1246 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr); 1247 1248 if ((handle = activate_context(actctx_manifest, &cookie))) 1249 { 1250 memset(&clsid, 0, sizeof(clsid)); 1251 hr = CoGetPSClsid(&IID_Testiface, &clsid); 1252 ok(hr == S_OK, "got 0x%08x\n", hr); 1253 ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", wine_dbgstr_guid(&clsid)); 1254 1255 memset(&clsid, 0, sizeof(clsid)); 1256 hr = CoGetPSClsid(&IID_Testiface2, &clsid); 1257 ok(hr == S_OK, "got 0x%08x\n", hr); 1258 ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", wine_dbgstr_guid(&clsid)); 1259 1260 memset(&clsid, 0, sizeof(clsid)); 1261 hr = CoGetPSClsid(&IID_Testiface3, &clsid); 1262 ok(hr == S_OK, "got 0x%08x\n", hr); 1263 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid)); 1264 1265 memset(&clsid, 0xaa, sizeof(clsid)); 1266 hr = CoGetPSClsid(&IID_Testiface4, &clsid); 1267 ok(hr == S_OK, "got 0x%08x\n", hr); 1268 ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", wine_dbgstr_guid(&clsid)); 1269 1270 /* register same interface and try to get CLSID back */ 1271 hr = CoRegisterPSClsid(&IID_Testiface, &IID_Testiface4); 1272 ok(hr == S_OK, "got 0x%08x\n", hr); 1273 memset(&clsid, 0, sizeof(clsid)); 1274 hr = CoGetPSClsid(&IID_Testiface, &clsid); 1275 ok(hr == S_OK, "got 0x%08x\n", hr); 1276 ok(IsEqualGUID(&clsid, &IID_Testiface4), "got clsid %s\n", wine_dbgstr_guid(&clsid)); 1277 1278 pDeactivateActCtx(0, cookie); 1279 pReleaseActCtx(handle); 1280 } 1281 1282 if (pRegDeleteKeyExA && 1283 (is_win64 || 1284 (pIsWow64Process && pIsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))) 1285 { 1286 static GUID IID_DeadBeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}}; 1287 static const char clsidDeadBeef[] = "{deadbeef-dead-beef-dead-beefdeadbeef}"; 1288 static const char clsidA[] = "{66666666-8888-7777-6666-555555555555}"; 1289 HKEY hkey_iface, hkey_psclsid; 1290 REGSAM opposite = is_win64 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY; 1291 1292 hr = CoGetPSClsid(&IID_DeadBeef, &clsid); 1293 ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr); 1294 1295 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, "Interface", 1296 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_iface, NULL); 1297 ok(!res, "RegCreateKeyEx returned %d\n", res); 1298 res = RegCreateKeyExA(hkey_iface, clsidDeadBeef, 1299 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey, NULL); 1300 if (res == ERROR_ACCESS_DENIED) 1301 { 1302 win_skip("Failed to create a key, skipping some of CoGetPSClsid() tests\n"); 1303 goto cleanup; 1304 } 1305 1306 ok(!res, "RegCreateKeyEx returned %d\n", res); 1307 res = RegCreateKeyExA(hkey, "ProxyStubClsid32", 1308 0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_psclsid, NULL); 1309 ok(!res, "RegCreateKeyEx returned %d\n", res); 1310 res = RegSetValueExA(hkey_psclsid, NULL, 0, REG_SZ, (const BYTE *)clsidA, strlen(clsidA)+1); 1311 ok(!res, "RegSetValueEx returned %d\n", res); 1312 RegCloseKey(hkey_psclsid); 1313 1314 hr = CoGetPSClsid(&IID_DeadBeef, &clsid); 1315 ok_ole_success(hr, "CoGetPSClsid"); 1316 ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid)); 1317 1318 res = pRegDeleteKeyExA(hkey, "ProxyStubClsid32", opposite, 0); 1319 ok(!res, "RegDeleteKeyEx returned %d\n", res); 1320 RegCloseKey(hkey); 1321 res = pRegDeleteKeyExA(hkey_iface, clsidDeadBeef, opposite, 0); 1322 ok(!res, "RegDeleteKeyEx returned %d\n", res); 1323 1324 cleanup: 1325 RegCloseKey(hkey_iface); 1326 } 1327 1328 CoUninitialize(); 1329 } 1330 1331 /* basic test, mainly for invalid arguments. see marshal.c for more */ 1332 static void test_CoUnmarshalInterface(void) 1333 { 1334 IUnknown *pProxy; 1335 IStream *pStream; 1336 HRESULT hr; 1337 1338 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy); 1339 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1340 1341 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1342 ok_ole_success(hr, "CreateStreamOnHGlobal"); 1343 1344 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy); 1345 todo_wine 1346 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr); 1347 1348 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1349 1350 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy); 1351 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr); 1352 1353 CoUninitialize(); 1354 1355 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL); 1356 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1357 1358 IStream_Release(pStream); 1359 } 1360 1361 static void test_CoGetInterfaceAndReleaseStream(void) 1362 { 1363 HRESULT hr; 1364 IUnknown *pUnk; 1365 1366 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1367 1368 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk); 1369 ok(hr == E_INVALIDARG, "hr %08x\n", hr); 1370 1371 CoUninitialize(); 1372 } 1373 1374 /* basic test, mainly for invalid arguments. see marshal.c for more */ 1375 static void test_CoMarshalInterface(void) 1376 { 1377 IStream *pStream; 1378 HRESULT hr; 1379 static const LARGE_INTEGER llZero; 1380 1381 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1382 1383 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1384 ok_ole_success(hr, "CreateStreamOnHGlobal"); 1385 1386 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1387 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1388 1389 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1390 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1391 1392 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1393 ok_ole_success(hr, "CoMarshalInterface"); 1394 1395 /* stream not rewound */ 1396 hr = CoReleaseMarshalData(pStream); 1397 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr); 1398 1399 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 1400 ok_ole_success(hr, "IStream_Seek"); 1401 1402 hr = CoReleaseMarshalData(pStream); 1403 ok_ole_success(hr, "CoReleaseMarshalData"); 1404 1405 IStream_Release(pStream); 1406 1407 CoUninitialize(); 1408 } 1409 1410 static void test_CoMarshalInterThreadInterfaceInStream(void) 1411 { 1412 IStream *pStream; 1413 HRESULT hr; 1414 IClassFactory *pProxy; 1415 1416 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1417 1418 cLocks = 0; 1419 1420 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL); 1421 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1422 1423 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream); 1424 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1425 1426 ok_no_locks(); 1427 1428 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream); 1429 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream"); 1430 1431 ok_more_than_one_lock(); 1432 1433 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1434 ok_ole_success(hr, "CoUnmarshalInterface"); 1435 1436 IClassFactory_Release(pProxy); 1437 IStream_Release(pStream); 1438 1439 ok_no_locks(); 1440 1441 CoUninitialize(); 1442 } 1443 1444 static void test_CoRegisterClassObject(void) 1445 { 1446 ULONG_PTR ctxcookie; 1447 HANDLE handle; 1448 DWORD cookie; 1449 HRESULT hr; 1450 IClassFactory *pcf; 1451 1452 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1453 1454 /* CLSCTX_INPROC_SERVER */ 1455 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1456 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); 1457 ok_ole_success(hr, "CoRegisterClassObject"); 1458 hr = CoRevokeClassObject(cookie); 1459 ok_ole_success(hr, "CoRevokeClassObject"); 1460 1461 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1462 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie); 1463 ok_ole_success(hr, "CoRegisterClassObject"); 1464 hr = CoRevokeClassObject(cookie); 1465 ok_ole_success(hr, "CoRevokeClassObject"); 1466 1467 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1468 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie); 1469 ok_ole_success(hr, "CoRegisterClassObject"); 1470 hr = CoRevokeClassObject(cookie); 1471 ok_ole_success(hr, "CoRevokeClassObject"); 1472 1473 /* CLSCTX_LOCAL_SERVER */ 1474 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1475 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie); 1476 ok_ole_success(hr, "CoRegisterClassObject"); 1477 hr = CoRevokeClassObject(cookie); 1478 ok_ole_success(hr, "CoRevokeClassObject"); 1479 1480 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1481 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie); 1482 ok_ole_success(hr, "CoRegisterClassObject"); 1483 hr = CoRevokeClassObject(cookie); 1484 ok_ole_success(hr, "CoRevokeClassObject"); 1485 1486 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1487 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie); 1488 ok_ole_success(hr, "CoRegisterClassObject"); 1489 hr = CoRevokeClassObject(cookie); 1490 ok_ole_success(hr, "CoRevokeClassObject"); 1491 1492 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */ 1493 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1494 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie); 1495 ok_ole_success(hr, "CoRegisterClassObject"); 1496 hr = CoRevokeClassObject(cookie); 1497 ok_ole_success(hr, "CoRevokeClassObject"); 1498 1499 /* test whether an object that doesn't support IClassFactory can be 1500 * registered for CLSCTX_LOCAL_SERVER */ 1501 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown, 1502 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie); 1503 ok_ole_success(hr, "CoRegisterClassObject"); 1504 hr = CoRevokeClassObject(cookie); 1505 ok_ole_success(hr, "CoRevokeClassObject"); 1506 1507 /* test whether registered class becomes invalid when apartment is destroyed */ 1508 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1509 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); 1510 ok_ole_success(hr, "CoRegisterClassObject"); 1511 1512 CoUninitialize(); 1513 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1514 1515 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, 1516 &IID_IClassFactory, (void **)&pcf); 1517 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n"); 1518 1519 /* crashes with at least win9x DCOM! */ 1520 if (0) 1521 CoRevokeClassObject(cookie); 1522 1523 /* test that object is accessible */ 1524 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER, 1525 REGCLS_MULTIPLEUSE, &cookie); 1526 ok(hr == S_OK, "got 0x%08x\n", hr); 1527 1528 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf); 1529 ok(hr == S_OK, "got 0x%08x\n", hr); 1530 IClassFactory_Release(pcf); 1531 1532 /* context now contains CLSID_WineOOPTest, test if registered one could still be used */ 1533 if ((handle = activate_context(actctx_manifest, &ctxcookie))) 1534 { 1535 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf); 1536 todo_wine 1537 ok(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), "got 0x%08x\n", hr); 1538 1539 pDeactivateActCtx(0, ctxcookie); 1540 pReleaseActCtx(handle); 1541 } 1542 1543 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf); 1544 ok(hr == S_OK, "got 0x%08x\n", hr); 1545 IClassFactory_Release(pcf); 1546 1547 hr = CoRevokeClassObject(cookie); 1548 ok(hr == S_OK, "got 0x%08x\n", hr); 1549 1550 CoUninitialize(); 1551 } 1552 1553 static HRESULT get_class_object(CLSCTX clsctx) 1554 { 1555 HRESULT hr; 1556 IClassFactory *pcf; 1557 1558 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory, 1559 (void **)&pcf); 1560 1561 if (SUCCEEDED(hr)) 1562 IClassFactory_Release(pcf); 1563 1564 return hr; 1565 } 1566 1567 static DWORD CALLBACK get_class_object_thread(LPVOID pv) 1568 { 1569 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv; 1570 HRESULT hr; 1571 1572 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1573 1574 hr = get_class_object(clsctx); 1575 1576 CoUninitialize(); 1577 1578 return hr; 1579 } 1580 1581 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv) 1582 { 1583 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv; 1584 HRESULT hr; 1585 IClassFactory *pcf; 1586 IMultiQI *pMQI; 1587 1588 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1589 1590 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory, 1591 (void **)&pcf); 1592 1593 if (SUCCEEDED(hr)) 1594 { 1595 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI); 1596 if (SUCCEEDED(hr)) 1597 IMultiQI_Release(pMQI); 1598 IClassFactory_Release(pcf); 1599 } 1600 1601 CoUninitialize(); 1602 1603 return hr; 1604 } 1605 1606 static DWORD CALLBACK register_class_object_thread(LPVOID pv) 1607 { 1608 HRESULT hr; 1609 DWORD cookie; 1610 1611 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1612 1613 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1614 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); 1615 1616 CoUninitialize(); 1617 1618 return hr; 1619 } 1620 1621 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv) 1622 { 1623 DWORD cookie = (DWORD_PTR)pv; 1624 HRESULT hr; 1625 1626 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1627 1628 hr = CoRevokeClassObject(cookie); 1629 1630 CoUninitialize(); 1631 1632 return hr; 1633 } 1634 1635 static void test_registered_object_thread_affinity(void) 1636 { 1637 HRESULT hr; 1638 DWORD cookie; 1639 HANDLE thread; 1640 DWORD tid; 1641 DWORD exitcode; 1642 1643 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1644 1645 /* CLSCTX_INPROC_SERVER */ 1646 1647 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1648 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); 1649 ok_ole_success(hr, "CoRegisterClassObject"); 1650 1651 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid); 1652 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); 1653 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 1654 GetExitCodeThread(thread, &exitcode); 1655 hr = exitcode; 1656 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object " 1657 "registered in different thread should return REGDB_E_CLASSNOTREG " 1658 "instead of 0x%08x\n", hr); 1659 1660 hr = get_class_object(CLSCTX_INPROC_SERVER); 1661 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same " 1662 "thread should return S_OK instead of 0x%08x\n", hr); 1663 1664 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid); 1665 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); 1666 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 1667 GetExitCodeThread(thread, &exitcode); 1668 hr = exitcode; 1669 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr); 1670 1671 hr = CoRevokeClassObject(cookie); 1672 ok_ole_success(hr, "CoRevokeClassObject"); 1673 1674 /* CLSCTX_LOCAL_SERVER */ 1675 1676 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 1677 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie); 1678 ok_ole_success(hr, "CoRegisterClassObject"); 1679 1680 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid); 1681 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); 1682 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1) 1683 { 1684 MSG msg; 1685 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 1686 { 1687 TranslateMessage(&msg); 1688 DispatchMessageA(&msg); 1689 } 1690 } 1691 GetExitCodeThread(thread, &exitcode); 1692 hr = exitcode; 1693 ok(hr == S_OK, "CoGetClassObject on local server object " 1694 "registered in different thread should return S_OK " 1695 "instead of 0x%08x\n", hr); 1696 1697 hr = get_class_object(CLSCTX_LOCAL_SERVER); 1698 ok(hr == S_OK, "CoGetClassObject on local server object registered in same " 1699 "thread should return S_OK instead of 0x%08x\n", hr); 1700 1701 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid); 1702 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); 1703 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 1704 GetExitCodeThread(thread, &exitcode); 1705 hr = exitcode; 1706 ok(hr == RPC_E_WRONG_THREAD || broken(hr == S_OK) /* win8 */, "CoRevokeClassObject called from different " 1707 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr); 1708 1709 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid); 1710 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); 1711 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 1712 GetExitCodeThread(thread, &exitcode); 1713 hr = exitcode; 1714 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different " 1715 "thread should return S_OK instead of 0x%08x\n", hr); 1716 1717 hr = CoRevokeClassObject(cookie); 1718 ok_ole_success(hr, "CoRevokeClassObject"); 1719 1720 CoUninitialize(); 1721 } 1722 1723 static DWORD CALLBACK free_libraries_thread(LPVOID p) 1724 { 1725 CoFreeUnusedLibraries(); 1726 return 0; 1727 } 1728 1729 static inline BOOL is_module_loaded(const char *module) 1730 { 1731 return GetModuleHandleA(module) != 0; 1732 } 1733 1734 static void test_CoFreeUnusedLibraries(void) 1735 { 1736 HRESULT hr; 1737 IUnknown *pUnk; 1738 DWORD tid; 1739 HANDLE thread; 1740 1741 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1742 1743 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n"); 1744 1745 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk); 1746 if (hr == REGDB_E_CLASSNOTREG) 1747 { 1748 skip("IE not installed so can't run CoFreeUnusedLibraries test\n"); 1749 CoUninitialize(); 1750 return; 1751 } 1752 ok_ole_success(hr, "CoCreateInstance"); 1753 1754 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n"); 1755 1756 ok(pUnk != NULL || 1757 broken(pUnk == NULL), /* win9x */ 1758 "Expected a valid pointer\n"); 1759 if (pUnk) 1760 IUnknown_Release(pUnk); 1761 1762 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n"); 1763 1764 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid); 1765 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 1766 CloseHandle(thread); 1767 1768 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n"); 1769 1770 CoFreeUnusedLibraries(); 1771 1772 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n"); 1773 1774 CoUninitialize(); 1775 } 1776 1777 static void test_CoGetObjectContext(void) 1778 { 1779 HRESULT hr; 1780 ULONG refs; 1781 IComThreadingInfo *pComThreadingInfo, *threadinginfo2; 1782 IContextCallback *pContextCallback; 1783 IObjContext *pObjContext; 1784 APTTYPE apttype; 1785 THDTYPE thdtype; 1786 GUID id, id2; 1787 1788 if (!pCoGetObjectContext) 1789 { 1790 win_skip("CoGetObjectContext not present\n"); 1791 return; 1792 } 1793 1794 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo); 1795 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr); 1796 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n"); 1797 1798 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1799 1800 test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE); 1801 1802 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo); 1803 ok_ole_success(hr, "CoGetObjectContext"); 1804 1805 threadinginfo2 = NULL; 1806 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&threadinginfo2); 1807 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr); 1808 ok(pComThreadingInfo == threadinginfo2, "got different instance\n"); 1809 IComThreadingInfo_Release(threadinginfo2); 1810 1811 hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, NULL); 1812 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 1813 1814 id = id2 = GUID_NULL; 1815 hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, &id); 1816 ok(hr == S_OK, "got 0x%08x\n", hr); 1817 1818 hr = CoGetCurrentLogicalThreadId(&id2); 1819 ok(IsEqualGUID(&id, &id2), "got %s, expected %s\n", wine_dbgstr_guid(&id), wine_dbgstr_guid(&id2)); 1820 1821 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype); 1822 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType"); 1823 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype); 1824 1825 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype); 1826 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType"); 1827 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype); 1828 1829 refs = IComThreadingInfo_Release(pComThreadingInfo); 1830 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs); 1831 1832 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback); 1833 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)"); 1834 1835 refs = IContextCallback_Release(pContextCallback); 1836 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs); 1837 1838 CoUninitialize(); 1839 1840 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 1841 1842 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo); 1843 ok_ole_success(hr, "CoGetObjectContext"); 1844 1845 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype); 1846 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType"); 1847 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype); 1848 1849 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype); 1850 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType"); 1851 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype); 1852 1853 refs = IComThreadingInfo_Release(pComThreadingInfo); 1854 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs); 1855 1856 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback); 1857 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)"); 1858 1859 refs = IContextCallback_Release(pContextCallback); 1860 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs); 1861 1862 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext); 1863 ok_ole_success(hr, "CoGetObjectContext"); 1864 1865 refs = IObjContext_Release(pObjContext); 1866 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs); 1867 1868 CoUninitialize(); 1869 } 1870 1871 typedef struct { 1872 IUnknown IUnknown_iface; 1873 LONG refs; 1874 } Test_CallContext; 1875 1876 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface) 1877 { 1878 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface); 1879 } 1880 1881 static HRESULT WINAPI Test_CallContext_QueryInterface( 1882 IUnknown *iface, 1883 REFIID riid, 1884 LPVOID *ppvObj) 1885 { 1886 if (ppvObj == NULL) return E_POINTER; 1887 1888 if (IsEqualGUID(riid, &IID_IUnknown)) 1889 { 1890 *ppvObj = iface; 1891 IUnknown_AddRef(iface); 1892 return S_OK; 1893 } 1894 1895 *ppvObj = NULL; 1896 return E_NOINTERFACE; 1897 } 1898 1899 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface) 1900 { 1901 Test_CallContext *This = impl_from_IUnknown(iface); 1902 return InterlockedIncrement(&This->refs); 1903 } 1904 1905 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface) 1906 { 1907 Test_CallContext *This = impl_from_IUnknown(iface); 1908 ULONG refs = InterlockedDecrement(&This->refs); 1909 if (!refs) 1910 HeapFree(GetProcessHeap(), 0, This); 1911 return refs; 1912 } 1913 1914 static const IUnknownVtbl TestCallContext_Vtbl = 1915 { 1916 Test_CallContext_QueryInterface, 1917 Test_CallContext_AddRef, 1918 Test_CallContext_Release 1919 }; 1920 1921 static void test_CoGetCallContext(void) 1922 { 1923 HRESULT hr; 1924 ULONG refs; 1925 IUnknown *pUnk; 1926 Test_CallContext *test_object; 1927 1928 if (!pCoSwitchCallContext) 1929 { 1930 skip("CoSwitchCallContext not present\n"); 1931 return; 1932 } 1933 1934 CoInitialize(NULL); 1935 1936 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext)); 1937 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl; 1938 test_object->refs = 1; 1939 1940 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk); 1941 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr); 1942 1943 pUnk = (IUnknown*)0xdeadbeef; 1944 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk); 1945 ok_ole_success(hr, "CoSwitchCallContext"); 1946 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk); 1947 refs = IUnknown_AddRef(&test_object->IUnknown_iface); 1948 ok(refs == 2, "Expected refcount 2, got %d\n", refs); 1949 IUnknown_Release(&test_object->IUnknown_iface); 1950 1951 pUnk = (IUnknown*)0xdeadbeef; 1952 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk); 1953 ok_ole_success(hr, "CoGetCallContext"); 1954 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n", 1955 &test_object->IUnknown_iface, pUnk); 1956 refs = IUnknown_AddRef(&test_object->IUnknown_iface); 1957 ok(refs == 3, "Expected refcount 3, got %d\n", refs); 1958 IUnknown_Release(&test_object->IUnknown_iface); 1959 IUnknown_Release(pUnk); 1960 1961 pUnk = (IUnknown*)0xdeadbeef; 1962 hr = pCoSwitchCallContext(NULL, &pUnk); 1963 ok_ole_success(hr, "CoSwitchCallContext"); 1964 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n", 1965 &test_object->IUnknown_iface, pUnk); 1966 refs = IUnknown_AddRef(&test_object->IUnknown_iface); 1967 ok(refs == 2, "Expected refcount 2, got %d\n", refs); 1968 IUnknown_Release(&test_object->IUnknown_iface); 1969 1970 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk); 1971 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr); 1972 1973 IUnknown_Release(&test_object->IUnknown_iface); 1974 1975 CoUninitialize(); 1976 } 1977 1978 static void test_CoGetContextToken(void) 1979 { 1980 HRESULT hr; 1981 ULONG refs; 1982 ULONG_PTR token, token2; 1983 IObjContext *ctx; 1984 1985 if (!pCoGetContextToken) 1986 { 1987 win_skip("CoGetContextToken not present\n"); 1988 return; 1989 } 1990 1991 token = 0xdeadbeef; 1992 hr = pCoGetContextToken(&token); 1993 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr); 1994 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token); 1995 1996 test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE); 1997 1998 CoInitialize(NULL); 1999 2000 test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE); 2001 2002 hr = pCoGetContextToken(NULL); 2003 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr); 2004 2005 token = 0; 2006 hr = pCoGetContextToken(&token); 2007 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr); 2008 ok(token, "Expected token != 0\n"); 2009 2010 token2 = 0; 2011 hr = pCoGetContextToken(&token2); 2012 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr); 2013 ok(token2 == token, "got different token\n"); 2014 2015 refs = IUnknown_AddRef((IUnknown *)token); 2016 ok(refs == 1, "Expected 1, got %u\n", refs); 2017 2018 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx); 2019 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr); 2020 ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n"); 2021 2022 refs = IObjContext_AddRef(ctx); 2023 ok(refs == 3, "Expected 3, got %u\n", refs); 2024 2025 refs = IObjContext_Release(ctx); 2026 ok(refs == 2, "Expected 2, got %u\n", refs); 2027 2028 refs = IUnknown_Release((IUnknown *)token); 2029 ok(refs == 1, "Expected 1, got %u\n", refs); 2030 2031 /* CoGetContextToken does not add a reference */ 2032 token = 0; 2033 hr = pCoGetContextToken(&token); 2034 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr); 2035 ok(token, "Expected token != 0\n"); 2036 ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n"); 2037 2038 refs = IObjContext_AddRef(ctx); 2039 ok(refs == 2, "Expected 1, got %u\n", refs); 2040 2041 refs = IObjContext_Release(ctx); 2042 ok(refs == 1, "Expected 0, got %u\n", refs); 2043 2044 refs = IObjContext_Release(ctx); 2045 ok(refs == 0, "Expected 0, got %u\n", refs); 2046 2047 CoUninitialize(); 2048 } 2049 2050 static void test_TreatAsClass(void) 2051 { 2052 HRESULT hr; 2053 CLSID out; 2054 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}}; 2055 static const char deadbeefA[] = "{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}"; 2056 IInternetProtocol *pIP = NULL; 2057 HKEY clsidkey, deadbeefkey; 2058 LONG lr; 2059 2060 if (!pCoGetTreatAsClass) 2061 { 2062 win_skip("CoGetTreatAsClass not present\n"); 2063 return; 2064 } 2065 2066 hr = pCoGetTreatAsClass(&deadbeef,&out); 2067 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr); 2068 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n"); 2069 2070 hr = pCoGetTreatAsClass(NULL, &out); 2071 ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr); 2072 ok(IsEqualGUID(&out, &deadbeef), "expected no change to the clsid\n"); 2073 2074 hr = pCoGetTreatAsClass(&deadbeef, NULL); 2075 ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr); 2076 2077 lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &clsidkey); 2078 ok(!lr, "Couldn't open CLSID key, error %d\n", lr); 2079 2080 lr = RegCreateKeyExA(clsidkey, deadbeefA, 0, NULL, 0, KEY_WRITE, NULL, &deadbeefkey, NULL); 2081 if (lr) { 2082 win_skip("CoGetTreatAsClass() tests will be skipped (failed to create a test key, error %d)\n", lr); 2083 RegCloseKey(clsidkey); 2084 return; 2085 } 2086 2087 hr = pCoTreatAsClass(&deadbeef, &deadbeef); 2088 ok(hr == REGDB_E_WRITEREGDB, "CoTreatAsClass gave wrong error: %08x\n", hr); 2089 2090 hr = pCoTreatAsClass(&deadbeef, &CLSID_FileProtocol); 2091 if(hr == REGDB_E_WRITEREGDB){ 2092 win_skip("Insufficient privileges to use CoTreatAsClass\n"); 2093 goto exit; 2094 } 2095 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr); 2096 2097 hr = pCoGetTreatAsClass(&deadbeef, &out); 2098 ok(hr == S_OK, "CoGetTreatAsClass failed: %08x\n",hr); 2099 ok(IsEqualGUID(&out, &CLSID_FileProtocol), "expected to get substituted clsid\n"); 2100 2101 OleInitialize(NULL); 2102 2103 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP); 2104 if(hr == REGDB_E_CLASSNOTREG) 2105 { 2106 win_skip("IE not installed so can't test CoCreateInstance\n"); 2107 goto exit; 2108 } 2109 2110 ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr); 2111 if(pIP){ 2112 IInternetProtocol_Release(pIP); 2113 pIP = NULL; 2114 } 2115 2116 hr = pCoTreatAsClass(&deadbeef, &CLSID_NULL); 2117 ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr); 2118 2119 hr = pCoGetTreatAsClass(&deadbeef, &out); 2120 ok(hr == S_FALSE, "expected S_FALSE got %08x\n", hr); 2121 ok(IsEqualGUID(&out, &deadbeef), "expected to get same clsid back\n"); 2122 2123 /* bizarrely, native's CoTreatAsClass takes some time to take effect in CoCreateInstance */ 2124 Sleep(200); 2125 2126 hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP); 2127 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance gave wrong error: %08x\n", hr); 2128 2129 if(pIP) 2130 IInternetProtocol_Release(pIP); 2131 2132 exit: 2133 OleUninitialize(); 2134 RegCloseKey(deadbeefkey); 2135 RegDeleteKeyA(clsidkey, deadbeefA); 2136 RegCloseKey(clsidkey); 2137 } 2138 2139 static void test_CoInitializeEx(void) 2140 { 2141 HRESULT hr; 2142 2143 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 2144 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr); 2145 2146 /* Calling OleInitialize for the first time should yield S_OK even with 2147 * apartment already initialized by previous CoInitialize(Ex) calls. */ 2148 hr = OleInitialize(NULL); 2149 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr); 2150 2151 /* Subsequent calls to OleInitialize should return S_FALSE */ 2152 hr = OleInitialize(NULL); 2153 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr); 2154 2155 /* Cleanup */ 2156 CoUninitialize(); 2157 OleUninitialize(); 2158 OleUninitialize(); 2159 } 2160 2161 static void test_OleInitialize_InitCounting(void) 2162 { 2163 HRESULT hr; 2164 IUnknown *pUnk; 2165 REFCLSID rclsid = &CLSID_InternetZoneManager; 2166 2167 /* 1. OleInitialize fails but OleUninitialize is still called: apartment stays initialized */ 2168 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED); 2169 ok(hr == S_OK, "CoInitializeEx(COINIT_MULTITHREADED) failed with error 0x%08x\n", hr); 2170 2171 hr = OleInitialize(NULL); 2172 ok(hr == RPC_E_CHANGED_MODE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", RPC_E_CHANGED_MODE, hr); 2173 OleUninitialize(); 2174 2175 pUnk = (IUnknown *)0xdeadbeef; 2176 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk); 2177 ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr); 2178 if (pUnk) IUnknown_Release(pUnk); 2179 2180 CoUninitialize(); 2181 2182 /* 2. Extra multiple OleUninitialize: apartment stays initialized until CoUninitialize */ 2183 hr = CoInitialize(NULL); 2184 ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr); 2185 2186 hr = OleInitialize(NULL); 2187 ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr); 2188 OleUninitialize(); 2189 OleUninitialize(); 2190 OleUninitialize(); 2191 2192 pUnk = (IUnknown *)0xdeadbeef; 2193 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk); 2194 ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr); 2195 if (pUnk) IUnknown_Release(pUnk); 2196 2197 CoUninitialize(); 2198 2199 pUnk = (IUnknown *)0xdeadbeef; 2200 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk); 2201 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr); 2202 if (pUnk) IUnknown_Release(pUnk); 2203 2204 /* 3. CoUninitialize does not formally deinit Ole */ 2205 hr = CoInitialize(NULL); 2206 ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr); 2207 2208 hr = OleInitialize(NULL); 2209 ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr); 2210 2211 CoUninitialize(); 2212 CoUninitialize(); 2213 2214 pUnk = (IUnknown *)0xdeadbeef; 2215 hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk); 2216 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr); 2217 /* COM is not initialized anymore */ 2218 if (pUnk) IUnknown_Release(pUnk); 2219 2220 hr = OleInitialize(NULL); 2221 ok(hr == S_FALSE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_FALSE, hr); 2222 /* ... but native OleInit returns S_FALSE as if Ole is considered initialized */ 2223 2224 OleUninitialize(); 2225 2226 } 2227 2228 static void test_OleRegGetMiscStatus(void) 2229 { 2230 ULONG_PTR cookie; 2231 HANDLE handle; 2232 DWORD status; 2233 HRESULT hr; 2234 2235 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, NULL); 2236 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 2237 2238 status = 0xdeadbeef; 2239 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status); 2240 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr); 2241 ok(status == 0, "got 0x%08x\n", status); 2242 2243 status = -1; 2244 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status); 2245 ok(hr == S_OK, "got 0x%08x\n", hr); 2246 ok(status == 0, "got 0x%08x\n", status); 2247 2248 if ((handle = activate_context(actctx_manifest, &cookie))) 2249 { 2250 status = 0; 2251 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status); 2252 ok(hr == S_OK, "got 0x%08x\n", hr); 2253 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status); 2254 2255 /* context data takes precedence over registration info */ 2256 status = 0; 2257 hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status); 2258 ok(hr == S_OK, "got 0x%08x\n", hr); 2259 ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status); 2260 2261 /* there's no such attribute in context */ 2262 status = -1; 2263 hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status); 2264 ok(hr == S_OK, "got 0x%08x\n", hr); 2265 ok(status == 0, "got 0x%08x\n", status); 2266 2267 pDeactivateActCtx(0, cookie); 2268 pReleaseActCtx(handle); 2269 } 2270 } 2271 2272 static void test_OleRegGetUserType(void) 2273 { 2274 static const WCHAR stdfont_usertypeW[] = {'S','t','a','n','d','a','r','d',' ','F','o','n','t',0}; 2275 static const WCHAR stdfont2_usertypeW[] = {'C','L','S','I','D','_','S','t','d','F','o','n','t',0}; 2276 static const WCHAR clsidkeyW[] = {'C','L','S','I','D',0}; 2277 static const WCHAR defvalueW[] = {'D','e','f','a','u','l','t',' ','N','a','m','e',0}; 2278 static const WCHAR auxvalue0W[] = {'A','u','x',' ','N','a','m','e',' ','0',0}; 2279 static const WCHAR auxvalue2W[] = {'A','u','x',' ','N','a','m','e',' ','2',0}; 2280 static const WCHAR auxvalue3W[] = {'A','u','x',' ','N','a','m','e',' ','3',0}; 2281 static const WCHAR auxvalue4W[] = {'A','u','x',' ','N','a','m','e',' ','4',0}; 2282 2283 static const char auxvalues[][16] = { 2284 "Aux Name 0", 2285 "Aux Name 1", 2286 "Aux Name 2", 2287 "Aux Name 3", 2288 "Aux Name 4" 2289 }; 2290 2291 HKEY clsidhkey, hkey, auxhkey, classkey; 2292 DWORD form, ret, disposition; 2293 WCHAR clsidW[39]; 2294 ULONG_PTR cookie; 2295 HANDLE handle; 2296 HRESULT hr; 2297 WCHAR *str; 2298 int i; 2299 2300 for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) { 2301 hr = OleRegGetUserType(&CLSID_Testclass, form, NULL); 2302 ok(hr == E_INVALIDARG, "form %u: got 0x%08x\n", form, hr); 2303 2304 str = (void*)0xdeadbeef; 2305 hr = OleRegGetUserType(&CLSID_Testclass, form, &str); 2306 ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr); 2307 ok(str == NULL, "form %u: got %p\n", form, str); 2308 2309 /* same string returned for StdFont for all form types */ 2310 str = NULL; 2311 hr = OleRegGetUserType(&CLSID_StdFont, form, &str); 2312 ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr); 2313 ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */, 2314 "form %u, got %s\n", form, wine_dbgstr_w(str)); 2315 CoTaskMemFree(str); 2316 } 2317 2318 if ((handle = activate_context(actctx_manifest, &cookie))) 2319 { 2320 for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) { 2321 str = (void*)0xdeadbeef; 2322 hr = OleRegGetUserType(&CLSID_Testclass, form, &str); 2323 ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr); 2324 ok(str == NULL, "form %u: got %s\n", form, wine_dbgstr_w(str)); 2325 2326 /* same string returned for StdFont for all form types */ 2327 str = NULL; 2328 hr = OleRegGetUserType(&CLSID_StdFont, form, &str); 2329 ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr); 2330 ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */, 2331 "form %u, got %s\n", form, wine_dbgstr_w(str)); 2332 CoTaskMemFree(str); 2333 } 2334 2335 pDeactivateActCtx(0, cookie); 2336 pReleaseActCtx(handle); 2337 } 2338 2339 /* test using registered CLSID */ 2340 StringFromGUID2(&CLSID_non_existent, clsidW, ARRAY_SIZE(clsidW)); 2341 2342 ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsidkeyW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &clsidhkey, &disposition); 2343 if (!ret) 2344 { 2345 ret = RegCreateKeyExW(clsidhkey, clsidW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &classkey, NULL); 2346 if (ret) 2347 RegCloseKey(clsidhkey); 2348 } 2349 2350 if (ret == ERROR_ACCESS_DENIED) 2351 { 2352 win_skip("Failed to create test key, skipping some of OleRegGetUserType() tests.\n"); 2353 return; 2354 } 2355 2356 ok(!ret, "failed to create a key, error %d\n", ret); 2357 2358 ret = RegSetValueExW(classkey, NULL, 0, REG_SZ, (const BYTE*)defvalueW, sizeof(defvalueW)); 2359 ok(!ret, "got error %d\n", ret); 2360 2361 ret = RegCreateKeyExA(classkey, "AuxUserType", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &auxhkey, NULL); 2362 ok(!ret, "got error %d\n", ret); 2363 2364 /* populate AuxUserType */ 2365 for (i = 0; i <= 4; i++) { 2366 char name[16]; 2367 2368 sprintf(name, "AuxUserType\\%d", i); 2369 ret = RegCreateKeyExA(classkey, name, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL); 2370 ok(!ret, "got error %d\n", ret); 2371 2372 ret = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE*)auxvalues[i], strlen(auxvalues[i])); 2373 ok(!ret, "got error %d\n", ret); 2374 RegCloseKey(hkey); 2375 } 2376 2377 str = NULL; 2378 hr = OleRegGetUserType(&CLSID_non_existent, 0, &str); 2379 ok(hr == S_OK, "got 0x%08x\n", hr); 2380 ok(!lstrcmpW(str, auxvalue0W), "got %s\n", wine_dbgstr_w(str)); 2381 CoTaskMemFree(str); 2382 2383 str = NULL; 2384 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_FULL, &str); 2385 ok(hr == S_OK, "got 0x%08x\n", hr); 2386 ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str)); 2387 CoTaskMemFree(str); 2388 2389 str = NULL; 2390 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_SHORT, &str); 2391 ok(hr == S_OK, "got 0x%08x\n", hr); 2392 ok(!lstrcmpW(str, auxvalue2W), "got %s\n", wine_dbgstr_w(str)); 2393 CoTaskMemFree(str); 2394 2395 str = NULL; 2396 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME, &str); 2397 ok(hr == S_OK, "got 0x%08x\n", hr); 2398 ok(!lstrcmpW(str, auxvalue3W), "got %s\n", wine_dbgstr_w(str)); 2399 CoTaskMemFree(str); 2400 2401 str = NULL; 2402 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+1, &str); 2403 ok(hr == S_OK, "got 0x%08x\n", hr); 2404 ok(!lstrcmpW(str, auxvalue4W), "got %s\n", wine_dbgstr_w(str)); 2405 CoTaskMemFree(str); 2406 2407 str = NULL; 2408 hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+2, &str); 2409 ok(hr == S_OK, "got 0x%08x\n", hr); 2410 ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str)); 2411 CoTaskMemFree(str); 2412 2413 /* registry cleanup */ 2414 for (i = 0; i <= 4; i++) 2415 { 2416 char name[2]; 2417 sprintf(name, "%d", i); 2418 RegDeleteKeyA(auxhkey, name); 2419 } 2420 RegCloseKey(auxhkey); 2421 RegDeleteKeyA(classkey, "AuxUserType"); 2422 RegCloseKey(classkey); 2423 RegDeleteKeyW(clsidhkey, clsidW); 2424 RegCloseKey(clsidhkey); 2425 if (disposition == REG_CREATED_NEW_KEY) 2426 RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID"); 2427 } 2428 2429 static void test_CoCreateGuid(void) 2430 { 2431 HRESULT hr; 2432 2433 hr = CoCreateGuid(NULL); 2434 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 2435 } 2436 2437 static void CALLBACK apc_test_proc(ULONG_PTR param) 2438 { 2439 /* nothing */ 2440 } 2441 2442 static DWORD CALLBACK release_semaphore_thread( LPVOID arg ) 2443 { 2444 HANDLE handle = arg; 2445 if (WaitForSingleObject(handle, 200) == WAIT_TIMEOUT) 2446 ReleaseSemaphore(handle, 1, NULL); 2447 return 0; 2448 } 2449 2450 static DWORD CALLBACK send_message_thread(LPVOID arg) 2451 { 2452 HWND hWnd = arg; 2453 Sleep(50); 2454 SendMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2455 return 0; 2456 } 2457 2458 static DWORD CALLBACK send_and_post_user_message_thread(void *arg) 2459 { 2460 HWND hwnd = arg; 2461 Sleep(30); 2462 SendMessageA(hwnd, WM_USER, 0, 0); 2463 PostMessageA(hwnd, WM_USER, 0, 0); 2464 return 0; 2465 } 2466 2467 static DWORD CALLBACK post_message_thread(LPVOID arg) 2468 { 2469 HWND hWnd = arg; 2470 Sleep(50); 2471 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2472 return 0; 2473 } 2474 2475 static const char cls_name[] = "cowait_test_class"; 2476 2477 static UINT cowait_msgs[100], cowait_msgs_first, cowait_msgs_last; 2478 2479 static void cowait_msgs_reset(void) 2480 { 2481 cowait_msgs_first = cowait_msgs_last = 0; 2482 } 2483 2484 #define cowait_msgs_expect_empty() _cowait_msgs_expect_empty(__LINE__) 2485 static void _cowait_msgs_expect_empty(unsigned line) 2486 { 2487 while(cowait_msgs_first < cowait_msgs_last) { 2488 ok_(__FILE__,line)(0, "unexpected message %u\n", cowait_msgs[cowait_msgs_first]); 2489 cowait_msgs_first++; 2490 } 2491 cowait_msgs_reset(); 2492 } 2493 2494 #define cowait_msgs_expect_notified(a) _cowait_msgs_expect_notified(__LINE__,a) 2495 static void _cowait_msgs_expect_notified(unsigned line, UINT expected_msg) 2496 { 2497 if(cowait_msgs_first == cowait_msgs_last) { 2498 ok_(__FILE__,line)(0, "expected message %u, received none\n", expected_msg); 2499 }else { 2500 ok_(__FILE__,line)(cowait_msgs[cowait_msgs_first] == expected_msg, 2501 "expected message %u, received %u \n", 2502 expected_msg, cowait_msgs[cowait_msgs_first]); 2503 cowait_msgs_first++; 2504 } 2505 } 2506 2507 #define cowait_msgs_expect_queued(a,b) _cowait_msgs_expect_queued(__LINE__,a,b) 2508 static void _cowait_msgs_expect_queued(unsigned line, HWND hwnd, UINT expected_msg) 2509 { 2510 MSG msg; 2511 BOOL success; 2512 2513 success = PeekMessageA(&msg, hwnd, expected_msg, expected_msg, PM_REMOVE); 2514 ok_(__FILE__,line)(success, "PeekMessageA failed: %u\n", GetLastError()); 2515 if(success) 2516 ok_(__FILE__,line)(msg.message == expected_msg, "unexpected message %u, expected %u\n", 2517 msg.message, expected_msg); 2518 } 2519 2520 static void flush_messages(void) 2521 { 2522 MSG msg; 2523 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )); 2524 } 2525 2526 static LRESULT CALLBACK cowait_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 2527 { 2528 if(cowait_msgs_last < ARRAY_SIZE(cowait_msgs)) 2529 cowait_msgs[cowait_msgs_last++] = msg; 2530 if(msg == WM_DDE_FIRST) 2531 return 6; 2532 return DefWindowProcA(hwnd, msg, wparam, lparam); 2533 } 2534 2535 static DWORD CALLBACK cowait_unmarshal_thread(void *arg) 2536 { 2537 IStream *stream = arg; 2538 IEnumOLEVERB *enum_verb; 2539 LARGE_INTEGER zero; 2540 IUnknown *unk; 2541 HRESULT hr; 2542 2543 CoInitialize(NULL); 2544 2545 zero.QuadPart = 0; 2546 hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); 2547 ok(hr == S_OK, "Seek failed: %08x\n", hr); 2548 2549 hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk); 2550 ok(hr == S_OK, "CoUnmarshalInterface failed: %08x\n", hr); 2551 2552 hr = IUnknown_QueryInterface(unk, &IID_IEnumOLEVERB, (void**)&enum_verb); 2553 ok(hr == S_OK, "QueryInterface failed: %08x\n", hr); 2554 2555 IEnumOLEVERB_Release(enum_verb); 2556 IUnknown_Release(unk); 2557 2558 CoUninitialize(); 2559 return 0; 2560 } 2561 2562 static DWORD CALLBACK test_CoWaitForMultipleHandles_thread(LPVOID arg) 2563 { 2564 HANDLE *handles = arg, event, thread; 2565 IStream *stream; 2566 BOOL success; 2567 DWORD index, tid; 2568 HRESULT hr; 2569 HWND hWnd; 2570 UINT uMSG = 0xc065; 2571 MSG msg; 2572 int ret; 2573 2574 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 2575 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr); 2576 2577 hWnd = CreateWindowExA(0, cls_name, "Test (thread)", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0); 2578 ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError()); 2579 2580 index = 0xdeadbeef; 2581 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2582 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index); 2583 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2584 ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index); 2585 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2586 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); 2587 2588 index = 0xdeadbeef; 2589 PostMessageA(hWnd, WM_USER, 0, 0); 2590 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index); 2591 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2592 ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index); 2593 success = PeekMessageA(&msg, hWnd, WM_USER, WM_USER, PM_REMOVE); 2594 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2595 2596 /* Even if CoWaitForMultipleHandles does not pump a message it peeks 2597 * at ALL of them */ 2598 index = 0xdeadbeef; 2599 PostMessageA(NULL, uMSG, 0, 0); 2600 2601 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index); 2602 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2603 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2604 2605 /* Make sure message was peeked at */ 2606 ret = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE); 2607 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret); 2608 2609 /* But not pumped */ 2610 success = PeekMessageA(&msg, NULL, uMSG, uMSG, PM_REMOVE); 2611 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2612 2613 DestroyWindow(hWnd); 2614 CoUninitialize(); 2615 2616 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 2617 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr); 2618 2619 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 2620 ok(hr == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hr); 2621 2622 hr = CoMarshalInterface(stream, &IID_IUnknown, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 2623 ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr); 2624 2625 event = CreateEventW(NULL, TRUE, FALSE, NULL); 2626 2627 PostQuitMessage(66); 2628 PostThreadMessageW(GetCurrentThreadId(), WM_QUIT, 0, 0); 2629 2630 hr = CoRegisterMessageFilter(&MessageFilter, NULL); 2631 ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr); 2632 2633 thread = CreateThread(NULL, 0, cowait_unmarshal_thread, stream, 0, &tid); 2634 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2635 hr = CoWaitForMultipleHandles(0, 50, 1, &event, &index); 2636 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2637 index = WaitForSingleObject(thread, 200); 2638 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2639 CloseHandle(thread); 2640 2641 hr = CoRegisterMessageFilter(NULL, NULL); 2642 ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr); 2643 2644 IStream_Release(stream); 2645 2646 CloseHandle(event); 2647 CoUninitialize(); 2648 return 0; 2649 } 2650 2651 static void test_CoWaitForMultipleHandles(void) 2652 { 2653 HANDLE handles[2], thread; 2654 DWORD index, tid; 2655 WNDCLASSEXA wc; 2656 BOOL success; 2657 HRESULT hr; 2658 HWND hWnd; 2659 MSG msg; 2660 2661 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 2662 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr); 2663 2664 memset(&wc, 0, sizeof(wc)); 2665 wc.cbSize = sizeof(wc); 2666 wc.style = CS_VREDRAW | CS_HREDRAW; 2667 wc.hInstance = GetModuleHandleA(0); 2668 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW); 2669 wc.hbrBackground = NULL; 2670 wc.lpszClassName = cls_name; 2671 wc.lpfnWndProc = cowait_window_proc; 2672 success = RegisterClassExA(&wc) != 0; 2673 ok(success, "RegisterClassExA failed %u\n", GetLastError()); 2674 2675 hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0); 2676 ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError()); 2677 handles[0] = CreateSemaphoreA(NULL, 1, 1, NULL); 2678 ok(handles[0] != 0, "CreateSemaphoreA failed %u\n", GetLastError()); 2679 handles[1] = CreateSemaphoreA(NULL, 1, 1, NULL); 2680 ok(handles[1] != 0, "CreateSemaphoreA failed %u\n", GetLastError()); 2681 2682 /* test without flags */ 2683 2684 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2685 hr = CoWaitForMultipleHandles(0, 50, 0, handles, NULL); 2686 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 2687 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2688 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2689 2690 index = 0xdeadbeef; 2691 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2692 hr = CoWaitForMultipleHandles(0, 50, 0, NULL, &index); 2693 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 2694 ok(index == 0, "expected index 0, got %u\n", index); 2695 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2696 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2697 2698 index = 0xdeadbeef; 2699 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2700 hr = CoWaitForMultipleHandles(0, 50, 0, handles, &index); 2701 ok(hr == RPC_E_NO_SYNC, "expected RPC_E_NO_SYNC, got 0x%08x\n", hr); 2702 ok(index == 0, "expected index 0, got %u\n", index); 2703 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2704 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2705 2706 index = 0xdeadbeef; 2707 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2708 hr = CoWaitForMultipleHandles(0, 50, 1, handles, &index); 2709 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 2710 ok(index == 0, "expected index 0, got %u\n", index); 2711 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2712 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2713 2714 index = 0xdeadbeef; 2715 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2716 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index); 2717 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 2718 ok(index == 1, "expected index 1, got %u\n", index); 2719 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2720 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2721 2722 index = 0xdeadbeef; 2723 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2724 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index); 2725 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2726 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2727 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2728 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); 2729 2730 /* test PostMessageA/SendMessageA from a different thread */ 2731 2732 index = 0xdeadbeef; 2733 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid); 2734 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2735 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 2736 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2737 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2738 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2739 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); 2740 index = WaitForSingleObject(thread, 200); 2741 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2742 CloseHandle(thread); 2743 2744 index = 0xdeadbeef; 2745 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid); 2746 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2747 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 2748 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2749 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2750 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2751 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); 2752 index = WaitForSingleObject(thread, 200); 2753 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2754 CloseHandle(thread); 2755 2756 ReleaseSemaphore(handles[0], 1, NULL); 2757 ReleaseSemaphore(handles[1], 1, NULL); 2758 2759 /* test with COWAIT_WAITALL */ 2760 2761 index = 0xdeadbeef; 2762 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2763 hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 50, 2, handles, &index); 2764 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 2765 ok(index == 0, "expected index 0, got %u\n", index); 2766 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2767 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2768 2769 index = 0xdeadbeef; 2770 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2771 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index); 2772 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2773 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2774 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2775 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); 2776 2777 ReleaseSemaphore(handles[0], 1, NULL); 2778 ReleaseSemaphore(handles[1], 1, NULL); 2779 2780 /* test with COWAIT_ALERTABLE */ 2781 2782 index = 0xdeadbeef; 2783 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2784 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 1, handles, &index); 2785 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 2786 ok(index == 0, "expected index 0, got %u\n", index); 2787 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2788 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2789 2790 index = 0xdeadbeef; 2791 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2792 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index); 2793 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 2794 ok(index == 1, "expected index 1, got %u\n", index); 2795 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2796 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2797 2798 index = 0xdeadbeef; 2799 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2800 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index); 2801 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2802 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2803 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2804 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); 2805 2806 index = 0xdeadbeef; 2807 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2808 success = QueueUserAPC(apc_test_proc, GetCurrentThread(), 0); 2809 ok(success, "QueueUserAPC failed %u\n", GetLastError()); 2810 hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index); 2811 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 2812 ok(index == WAIT_IO_COMPLETION, "expected index WAIT_IO_COMPLETION, got %u\n", index); 2813 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2814 ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); 2815 2816 /* test with COWAIT_INPUTAVAILABLE (semaphores are still locked) */ 2817 2818 index = 0xdeadbeef; 2819 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2820 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE); 2821 ok(success, "PeekMessageA returned FALSE\n"); 2822 hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index); 2823 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2824 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2825 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2826 ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); 2827 2828 index = 0xdeadbeef; 2829 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2830 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE); 2831 ok(success, "PeekMessageA returned FALSE\n"); 2832 thread = CreateThread(NULL, 0, release_semaphore_thread, handles[1], 0, &tid); 2833 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2834 hr = CoWaitForMultipleHandles(COWAIT_INPUTAVAILABLE, 50, 2, handles, &index); 2835 ok(hr == RPC_S_CALLPENDING || broken(hr == E_INVALIDARG) || broken(hr == S_OK) /* Win 8 */, 2836 "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2837 if (hr != S_OK) ReleaseSemaphore(handles[1], 1, NULL); 2838 ok(index == 0 || broken(index == 1) /* Win 8 */, "expected index 0, got %u\n", index); 2839 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2840 ok(!success || broken(success && hr == E_INVALIDARG), 2841 "CoWaitForMultipleHandles didn't pump any messages\n"); 2842 index = WaitForSingleObject(thread, 200); 2843 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2844 CloseHandle(thread); 2845 2846 cowait_msgs_reset(); 2847 PostMessageA(hWnd, 0, 0, 0); 2848 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2849 PostMessageA(hWnd, WM_USER+1, 0, 0); 2850 PostMessageA(hWnd, WM_DDE_FIRST+1, 0, 0); 2851 thread = CreateThread(NULL, 0, send_and_post_user_message_thread, hWnd, 0, &tid); 2852 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2853 2854 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 2855 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2856 2857 cowait_msgs_expect_notified(WM_DDE_FIRST); 2858 cowait_msgs_expect_notified(WM_DDE_FIRST+1); 2859 cowait_msgs_expect_notified(WM_USER); 2860 cowait_msgs_expect_empty(); 2861 cowait_msgs_expect_queued(hWnd, WM_USER); 2862 cowait_msgs_expect_queued(hWnd, WM_USER+1); 2863 flush_messages(); 2864 2865 index = WaitForSingleObject(thread, 200); 2866 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2867 CloseHandle(thread); 2868 2869 /* test behaviour of WM_QUIT (semaphores are still locked) */ 2870 2871 PostMessageA(hWnd, WM_QUIT, 40, 0); 2872 memset(&msg, 0, sizeof(msg)); 2873 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE); 2874 ok(success, "PeekMessageA failed, error %u\n", GetLastError()); 2875 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message); 2876 ok(msg.wParam == 40, "expected msg.wParam = 40, got %lu\n", msg.wParam); 2877 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE); 2878 ok(!success, "PeekMessageA succeeded\n"); 2879 2880 cowait_msgs_reset(); 2881 PostMessageA(hWnd, WM_QUIT, 40, 0); 2882 PostMessageA(hWnd, 0, 0, 0); 2883 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2884 PostMessageA(hWnd, WM_USER+1, 0, 0); 2885 PostMessageA(hWnd, WM_DDE_FIRST+1, 0, 0); 2886 thread = CreateThread(NULL, 0, send_and_post_user_message_thread, hWnd, 0, &tid); 2887 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2888 2889 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 2890 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2891 2892 cowait_msgs_expect_notified(WM_DDE_FIRST); 2893 cowait_msgs_expect_notified(WM_DDE_FIRST+1); 2894 cowait_msgs_expect_notified(WM_USER); 2895 cowait_msgs_expect_empty(); 2896 cowait_msgs_expect_queued(hWnd, WM_USER); 2897 flush_messages(); 2898 2899 index = WaitForSingleObject(thread, 200); 2900 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2901 CloseHandle(thread); 2902 2903 index = 0xdeadbeef; 2904 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2905 PostMessageA(hWnd, WM_QUIT, 41, 0); 2906 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid); 2907 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2908 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 2909 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2910 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2911 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2912 todo_wine 2913 ok(success || broken(!success) /* Win 2000/XP/8 */, "PeekMessageA failed, error %u\n", GetLastError()); 2914 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2915 ok(!success, "PeekMessageA succeeded\n"); 2916 memset(&msg, 0, sizeof(msg)); 2917 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE); 2918 todo_wine 2919 ok(!success || broken(success) /* Win 2000/XP/8 */, "PeekMessageA succeeded\n"); 2920 if (success) 2921 { 2922 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message); 2923 ok(msg.wParam == 41, "expected msg.wParam = 41, got %lu\n", msg.wParam); 2924 } 2925 index = WaitForSingleObject(thread, 200); 2926 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2927 CloseHandle(thread); 2928 2929 index = 0xdeadbeef; 2930 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2931 PostMessageA(hWnd, WM_QUIT, 42, 0); 2932 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid); 2933 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2934 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 2935 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2936 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2937 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2938 ok(!success, "CoWaitForMultipleHandles didn't pump all WM_DDE_FIRST messages\n"); 2939 memset(&msg, 0, sizeof(msg)); 2940 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE); 2941 ok(success, "PeekMessageA failed, error %u\n", GetLastError()); 2942 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message); 2943 ok(msg.wParam == 42, "expected msg.wParam = 42, got %lu\n", msg.wParam); 2944 index = WaitForSingleObject(thread, 200); 2945 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2946 CloseHandle(thread); 2947 2948 PostQuitMessage(43); 2949 memset(&msg, 0, sizeof(msg)); 2950 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE); 2951 ok(success || broken(!success) /* Win 8 */, "PeekMessageA failed, error %u\n", GetLastError()); 2952 if (!success) 2953 win_skip("PostQuitMessage didn't queue a WM_QUIT message, skipping tests\n"); 2954 else 2955 { 2956 ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message); 2957 ok(msg.wParam == 43, "expected msg.wParam = 43, got %lu\n", msg.wParam); 2958 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE); 2959 ok(!success, "PeekMessageA succeeded\n"); 2960 2961 index = 0xdeadbeef; 2962 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2963 PostQuitMessage(44); 2964 thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid); 2965 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2966 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 2967 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2968 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2969 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2970 ok(success, "PeekMessageA failed, error %u\n", GetLastError()); 2971 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2972 ok(!success, "PeekMessageA succeeded\n"); 2973 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE); 2974 ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n"); 2975 index = WaitForSingleObject(thread, 200); 2976 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2977 CloseHandle(thread); 2978 2979 index = 0xdeadbeef; 2980 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 2981 PostQuitMessage(45); 2982 thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid); 2983 ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError()); 2984 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 2985 ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); 2986 ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index); 2987 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2988 ok(success, "PeekMessageA failed, error %u\n", GetLastError()); 2989 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 2990 ok(!success, "PeekMessageA succeeded\n"); 2991 success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE); 2992 ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n"); 2993 index = WaitForSingleObject(thread, 200); 2994 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 2995 CloseHandle(thread); 2996 } 2997 2998 /* test message pumping when CoWaitForMultipleHandles is called from non main apartment thread */ 2999 thread = CreateThread(NULL, 0, test_CoWaitForMultipleHandles_thread, handles, 0, &tid); 3000 index = WaitForSingleObject(thread, 500); 3001 ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 3002 CloseHandle(thread); 3003 3004 CoUninitialize(); 3005 3006 /* If COM was not initialized, messages are neither pumped nor peeked at */ 3007 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 3008 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 3009 ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr); 3010 success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE); 3011 ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success); 3012 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 3013 ok(success, "PeekMessage failed: %u\n", GetLastError()); 3014 3015 /* same in an MTA */ 3016 CoInitializeEx(NULL, COINIT_MULTITHREADED); 3017 3018 PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); 3019 hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); 3020 ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr); 3021 success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE); 3022 ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success); 3023 success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); 3024 ok(success, "PeekMessage failed: %u\n", GetLastError()); 3025 3026 CoUninitialize(); 3027 3028 CloseHandle(handles[0]); 3029 CloseHandle(handles[1]); 3030 DestroyWindow(hWnd); 3031 3032 success = UnregisterClassA(cls_name, GetModuleHandleA(0)); 3033 ok(success, "UnregisterClass failed %u\n", GetLastError()); 3034 } 3035 3036 static void test_CoGetMalloc(void) 3037 { 3038 IMalloc *imalloc; 3039 HRESULT hr; 3040 3041 if (0) /* crashes on native */ 3042 hr = CoGetMalloc(0, NULL); 3043 3044 imalloc = (void*)0xdeadbeef; 3045 hr = CoGetMalloc(0, &imalloc); 3046 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3047 ok(imalloc == NULL, "got %p\n", imalloc); 3048 3049 imalloc = (void*)0xdeadbeef; 3050 hr = CoGetMalloc(MEMCTX_SHARED, &imalloc); 3051 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3052 ok(imalloc == NULL, "got %p\n", imalloc); 3053 3054 imalloc = (void*)0xdeadbeef; 3055 hr = CoGetMalloc(MEMCTX_MACSYSTEM, &imalloc); 3056 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3057 ok(imalloc == NULL, "got %p\n", imalloc); 3058 3059 imalloc = (void*)0xdeadbeef; 3060 hr = CoGetMalloc(MEMCTX_UNKNOWN, &imalloc); 3061 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3062 ok(imalloc == NULL, "got %p\n", imalloc); 3063 3064 imalloc = (void*)0xdeadbeef; 3065 hr = CoGetMalloc(MEMCTX_SAME, &imalloc); 3066 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3067 ok(imalloc == NULL, "got %p\n", imalloc); 3068 3069 imalloc = NULL; 3070 hr = CoGetMalloc(MEMCTX_TASK, &imalloc); 3071 ok(hr == S_OK, "got 0x%08x\n", hr); 3072 ok(imalloc != NULL, "got %p\n", imalloc); 3073 IMalloc_Release(imalloc); 3074 } 3075 3076 static void test_CoGetApartmentType(void) 3077 { 3078 APTTYPEQUALIFIER qualifier; 3079 APTTYPE type; 3080 HRESULT hr; 3081 3082 if (!pCoGetApartmentType) 3083 { 3084 win_skip("CoGetApartmentType not present\n"); 3085 return; 3086 } 3087 3088 hr = pCoGetApartmentType(NULL, NULL); 3089 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr); 3090 3091 type = 0xdeadbeef; 3092 hr = pCoGetApartmentType(&type, NULL); 3093 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr); 3094 ok(type == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", type); 3095 3096 qualifier = 0xdeadbeef; 3097 hr = pCoGetApartmentType(NULL, &qualifier); 3098 ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr); 3099 ok(qualifier == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", qualifier); 3100 3101 type = 0xdeadbeef; 3102 qualifier = 0xdeadbeef; 3103 hr = pCoGetApartmentType(&type, &qualifier); 3104 ok(hr == CO_E_NOTINITIALIZED, "CoGetApartmentType succeeded, error: 0x%08x\n", hr); 3105 ok(type == APTTYPE_CURRENT, "Expected APTTYPE_CURRENT, got %u\n", type); 3106 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier); 3107 3108 type = 0xdeadbeef; 3109 qualifier = 0xdeadbeef; 3110 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 3111 ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr); 3112 hr = pCoGetApartmentType(&type, &qualifier); 3113 ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr); 3114 ok(type == APTTYPE_MAINSTA, "Expected APTTYPE_MAINSTA, got %u\n", type); 3115 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier); 3116 CoUninitialize(); 3117 3118 type = 0xdeadbeef; 3119 qualifier = 0xdeadbeef; 3120 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED); 3121 ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr); 3122 hr = pCoGetApartmentType(&type, &qualifier); 3123 ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr); 3124 ok(type == APTTYPE_MTA, "Expected APTTYPE_MTA, got %u\n", type); 3125 ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier); 3126 CoUninitialize(); 3127 } 3128 3129 static HRESULT WINAPI testspy_QI(IMallocSpy *iface, REFIID riid, void **obj) 3130 { 3131 if (IsEqualIID(riid, &IID_IMallocSpy) || IsEqualIID(riid, &IID_IUnknown)) 3132 { 3133 *obj = iface; 3134 IMallocSpy_AddRef(iface); 3135 return S_OK; 3136 } 3137 3138 return E_NOINTERFACE; 3139 } 3140 3141 static ULONG WINAPI testspy_AddRef(IMallocSpy *iface) 3142 { 3143 return 2; 3144 } 3145 3146 static ULONG WINAPI testspy_Release(IMallocSpy *iface) 3147 { 3148 return 1; 3149 } 3150 3151 static SIZE_T WINAPI testspy_PreAlloc(IMallocSpy *iface, SIZE_T cb) 3152 { 3153 ok(0, "unexpected call\n"); 3154 return 0; 3155 } 3156 3157 static void* WINAPI testspy_PostAlloc(IMallocSpy *iface, void *ptr) 3158 { 3159 ok(0, "unexpected call\n"); 3160 return NULL; 3161 } 3162 3163 static void* WINAPI testspy_PreFree(IMallocSpy *iface, void *ptr, BOOL spyed) 3164 { 3165 ok(0, "unexpected call\n"); 3166 return NULL; 3167 } 3168 3169 static void WINAPI testspy_PostFree(IMallocSpy *iface, BOOL spyed) 3170 { 3171 ok(0, "unexpected call\n"); 3172 } 3173 3174 static SIZE_T WINAPI testspy_PreRealloc(IMallocSpy *iface, void *ptr, SIZE_T cb, void **newptr, BOOL spyed) 3175 { 3176 ok(0, "unexpected call\n"); 3177 return 0; 3178 } 3179 3180 static void* WINAPI testspy_PostRealloc(IMallocSpy *iface, void *ptr, BOOL spyed) 3181 { 3182 ok(0, "unexpected call\n"); 3183 return NULL; 3184 } 3185 3186 static void* WINAPI testspy_PreGetSize(IMallocSpy *iface, void *ptr, BOOL spyed) 3187 { 3188 ok(0, "unexpected call\n"); 3189 return NULL; 3190 } 3191 3192 static SIZE_T WINAPI testspy_PostGetSize(IMallocSpy *iface, SIZE_T actual, BOOL spyed) 3193 { 3194 ok(0, "unexpected call\n"); 3195 return 0; 3196 } 3197 3198 static void* WINAPI testspy_PreDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed) 3199 { 3200 ok(0, "unexpected call\n"); 3201 return NULL; 3202 } 3203 3204 static int WINAPI testspy_PostDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed, int actual) 3205 { 3206 ok(0, "unexpected call\n"); 3207 return 0; 3208 } 3209 3210 static void WINAPI testspy_PreHeapMinimize(IMallocSpy *iface) 3211 { 3212 ok(0, "unexpected call\n"); 3213 } 3214 3215 static void WINAPI testspy_PostHeapMinimize(IMallocSpy *iface) 3216 { 3217 ok(0, "unexpected call\n"); 3218 } 3219 3220 static const IMallocSpyVtbl testspyvtbl = 3221 { 3222 testspy_QI, 3223 testspy_AddRef, 3224 testspy_Release, 3225 testspy_PreAlloc, 3226 testspy_PostAlloc, 3227 testspy_PreFree, 3228 testspy_PostFree, 3229 testspy_PreRealloc, 3230 testspy_PostRealloc, 3231 testspy_PreGetSize, 3232 testspy_PostGetSize, 3233 testspy_PreDidAlloc, 3234 testspy_PostDidAlloc, 3235 testspy_PreHeapMinimize, 3236 testspy_PostHeapMinimize 3237 }; 3238 3239 static IMallocSpy testspy = { &testspyvtbl }; 3240 3241 static void test_IMallocSpy(void) 3242 { 3243 IMalloc *imalloc; 3244 HRESULT hr; 3245 3246 hr = CoRegisterMallocSpy(NULL); 3247 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3248 3249 hr = CoRevokeMallocSpy(); 3250 ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr); 3251 3252 hr = CoRegisterMallocSpy(&testspy); 3253 ok(hr == S_OK, "got 0x%08x\n", hr); 3254 3255 hr = CoRegisterMallocSpy(NULL); 3256 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3257 3258 hr = CoRegisterMallocSpy(&testspy); 3259 ok(hr == CO_E_OBJISREG, "got 0x%08x\n", hr); 3260 3261 imalloc = NULL; 3262 hr = CoGetMalloc(MEMCTX_TASK, &imalloc); 3263 ok(hr == S_OK, "got 0x%08x\n", hr); 3264 ok(imalloc != NULL, "got %p\n", imalloc); 3265 3266 IMalloc_Free(imalloc, NULL); 3267 3268 IMalloc_Release(imalloc); 3269 3270 hr = CoRevokeMallocSpy(); 3271 ok(hr == S_OK, "got 0x%08x\n", hr); 3272 3273 hr = CoRevokeMallocSpy(); 3274 ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr); 3275 } 3276 3277 static void test_CoGetCurrentLogicalThreadId(void) 3278 { 3279 HRESULT hr; 3280 GUID id; 3281 3282 hr = CoGetCurrentLogicalThreadId(NULL); 3283 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3284 3285 id = GUID_NULL; 3286 hr = CoGetCurrentLogicalThreadId(&id); 3287 ok(hr == S_OK, "got 0x%08x\n", hr); 3288 ok(!IsEqualGUID(&id, &GUID_NULL), "got null id\n"); 3289 } 3290 3291 static HRESULT WINAPI testinitialize_QI(IInitializeSpy *iface, REFIID riid, void **obj) 3292 { 3293 if (IsEqualIID(riid, &IID_IInitializeSpy) || IsEqualIID(riid, &IID_IUnknown)) 3294 { 3295 *obj = iface; 3296 IInitializeSpy_AddRef(iface); 3297 return S_OK; 3298 } 3299 3300 *obj = NULL; 3301 return E_NOINTERFACE; 3302 } 3303 3304 static ULONG WINAPI testinitialize_AddRef(IInitializeSpy *iface) 3305 { 3306 return 2; 3307 } 3308 3309 static ULONG WINAPI testinitialize_Release(IInitializeSpy *iface) 3310 { 3311 return 1; 3312 } 3313 3314 static DWORD expected_coinit_flags; 3315 static ULARGE_INTEGER init_cookies[3]; 3316 static BOOL revoke_spies_on_uninit; 3317 3318 static HRESULT WINAPI testinitialize_PreInitialize(IInitializeSpy *iface, DWORD coinit, DWORD aptrefs) 3319 { 3320 CHECK_EXPECT2(PreInitialize); 3321 ok(coinit == expected_coinit_flags, "Unexpected init flags %#x, expected %#x.\n", coinit, expected_coinit_flags); 3322 return S_OK; 3323 } 3324 3325 static HRESULT WINAPI testinitialize_PostInitialize(IInitializeSpy *iface, HRESULT hr, DWORD coinit, DWORD aptrefs) 3326 { 3327 CHECK_EXPECT2(PostInitialize); 3328 ok(coinit == expected_coinit_flags, "Unexpected init flags %#x, expected %#x.\n", coinit, expected_coinit_flags); 3329 return hr; 3330 } 3331 3332 static HRESULT WINAPI testinitialize_PreUninitialize(IInitializeSpy *iface, DWORD aptrefs) 3333 { 3334 HRESULT hr; 3335 CHECK_EXPECT2(PreUninitialize); 3336 if (revoke_spies_on_uninit) 3337 { 3338 hr = CoRevokeInitializeSpy(init_cookies[0]); 3339 ok(hr == S_OK, "got 0x%08x\n", hr); 3340 3341 hr = CoRevokeInitializeSpy(init_cookies[1]); 3342 ok(hr == S_OK, "got 0x%08x\n", hr); 3343 3344 hr = CoRevokeInitializeSpy(init_cookies[2]); 3345 ok(hr == S_OK, "got 0x%08x\n", hr); 3346 3347 revoke_spies_on_uninit = FALSE; 3348 } 3349 return S_OK; 3350 } 3351 3352 static HRESULT WINAPI testinitialize_PostUninitialize(IInitializeSpy *iface, DWORD aptrefs) 3353 { 3354 CHECK_EXPECT2(PostUninitialize); 3355 return E_NOTIMPL; 3356 } 3357 3358 static const IInitializeSpyVtbl testinitializevtbl = 3359 { 3360 testinitialize_QI, 3361 testinitialize_AddRef, 3362 testinitialize_Release, 3363 testinitialize_PreInitialize, 3364 testinitialize_PostInitialize, 3365 testinitialize_PreUninitialize, 3366 testinitialize_PostUninitialize 3367 }; 3368 3369 static IInitializeSpy testinitialize = { &testinitializevtbl }; 3370 3371 static DWORD WINAPI test_init_spies_proc(void *arg) 3372 { 3373 HRESULT hr; 3374 3375 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); 3376 ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr); 3377 3378 hr = CoRevokeInitializeSpy(init_cookies[2]); 3379 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3380 3381 CoUninitialize(); 3382 return 0; 3383 } 3384 3385 static void test_IInitializeSpy(BOOL mt) 3386 { 3387 HRESULT hr; 3388 3389 if (mt) 3390 { 3391 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED); 3392 ok(hr == S_OK, "CoInitializeEx failed: %#x\n", hr); 3393 } 3394 3395 hr = CoRegisterInitializeSpy(NULL, NULL); 3396 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3397 3398 init_cookies[0].QuadPart = 1; 3399 hr = CoRegisterInitializeSpy(NULL, &init_cookies[0]); 3400 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3401 ok(init_cookies[0].QuadPart == 1, "got wrong cookie\n"); 3402 3403 hr = CoRegisterInitializeSpy(&testinitialize, NULL); 3404 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3405 3406 init_cookies[0].HighPart = 0; 3407 init_cookies[0].LowPart = 1; 3408 hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[0]); 3409 ok(hr == S_OK, "got 0x%08x\n", hr); 3410 ok(init_cookies[0].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[0].HighPart, 3411 GetCurrentThreadId()); 3412 if (!mt) ok(init_cookies[0].LowPart == 0, "got wrong low part 0x%x\n", init_cookies[0].LowPart); 3413 3414 /* register same instance one more time */ 3415 init_cookies[1].HighPart = 0; 3416 init_cookies[1].LowPart = 0; 3417 hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[1]); 3418 ok(hr == S_OK, "got 0x%08x\n", hr); 3419 ok(init_cookies[1].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[1].HighPart, 3420 GetCurrentThreadId()); 3421 if (!mt) ok(init_cookies[1].LowPart == 1, "got wrong low part 0x%x\n", init_cookies[1].LowPart); 3422 3423 init_cookies[2].HighPart = 0; 3424 init_cookies[2].LowPart = 0; 3425 hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[2]); 3426 ok(hr == S_OK, "got 0x%08x\n", hr); 3427 ok(init_cookies[2].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[2].HighPart, 3428 GetCurrentThreadId()); 3429 if (!mt) ok(init_cookies[2].LowPart == 2, "got wrong low part 0x%x\n", init_cookies[2].LowPart); 3430 3431 hr = CoRevokeInitializeSpy(init_cookies[1]); 3432 ok(hr == S_OK, "got 0x%08x\n", hr); 3433 3434 hr = CoRevokeInitializeSpy(init_cookies[1]); 3435 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3436 3437 init_cookies[1].HighPart = 0; 3438 init_cookies[1].LowPart = 0; 3439 hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[1]); 3440 ok(hr == S_OK, "got 0x%08x\n", hr); 3441 ok(init_cookies[1].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[1].HighPart, 3442 GetCurrentThreadId()); 3443 if (!mt) ok(init_cookies[1].LowPart == 1, "got wrong low part 0x%x\n", init_cookies[1].LowPart); 3444 3445 SET_EXPECT(PreInitialize); 3446 SET_EXPECT(PostInitialize); 3447 hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE)); 3448 ok(hr == (mt ? S_FALSE : S_OK), "Failed to initialize COM, hr %#x.\n", hr); 3449 CHECK_CALLED(PreInitialize, 3); 3450 CHECK_CALLED(PostInitialize, 3); 3451 3452 if (mt) 3453 { 3454 HANDLE thread; 3455 thread = CreateThread(NULL, 0, test_init_spies_proc, NULL, 0, NULL); 3456 ok(thread != NULL, "CreateThread failed: %u\n", GetLastError()); 3457 ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); 3458 } 3459 3460 SET_EXPECT(PreInitialize); 3461 SET_EXPECT(PostInitialize); 3462 hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE)); 3463 ok(hr == S_FALSE, "Failed to initialize COM, hr %#x.\n", hr); 3464 CHECK_CALLED(PreInitialize, 3); 3465 CHECK_CALLED(PostInitialize, 3); 3466 3467 SET_EXPECT(PreUninitialize); 3468 SET_EXPECT(PostUninitialize); 3469 CoUninitialize(); 3470 CHECK_CALLED(PreUninitialize, 3); 3471 CHECK_CALLED(PostUninitialize, 3); 3472 3473 SET_EXPECT(PreUninitialize); 3474 SET_EXPECT(PostUninitialize); 3475 CoUninitialize(); 3476 CHECK_CALLED(PreUninitialize, 3); 3477 CHECK_CALLED(PostUninitialize, 3); 3478 3479 if (mt) 3480 { 3481 SET_EXPECT(PreUninitialize); 3482 SET_EXPECT(PostUninitialize); 3483 CoUninitialize(); 3484 CHECK_CALLED(PreUninitialize, 3); 3485 CHECK_CALLED(PostUninitialize, 3); 3486 } 3487 3488 SET_EXPECT(PreInitialize); 3489 SET_EXPECT(PostInitialize); 3490 hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE)); 3491 ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr); 3492 CHECK_CALLED(PreInitialize, 3); 3493 CHECK_CALLED(PostInitialize, 3); 3494 3495 SET_EXPECT(PreUninitialize); 3496 revoke_spies_on_uninit = TRUE; 3497 CoUninitialize(); 3498 CHECK_CALLED(PreUninitialize, 1); 3499 } 3500 3501 static HRESULT g_persistfile_qi_ret; 3502 static HRESULT g_persistfile_load_ret; 3503 static HRESULT WINAPI testinstance_QI(IPersistFile *iface, REFIID riid, void **obj) 3504 { 3505 if (IsEqualIID(riid, &IID_IUnknown)) { 3506 *obj = iface; 3507 IUnknown_AddRef(iface); 3508 return S_OK; 3509 } 3510 3511 if (IsEqualIID(riid, &IID_IPersistFile)) { 3512 if (SUCCEEDED(g_persistfile_qi_ret)) { 3513 *obj = iface; 3514 IUnknown_AddRef(iface); 3515 } 3516 else 3517 *obj = NULL; 3518 return g_persistfile_qi_ret; 3519 } 3520 3521 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); 3522 *obj = NULL; 3523 return E_NOINTERFACE; 3524 } 3525 3526 static ULONG WINAPI testinstance_AddRef(IPersistFile *iface) 3527 { 3528 return 2; 3529 } 3530 3531 static ULONG WINAPI testinstance_Release(IPersistFile *iface) 3532 { 3533 return 1; 3534 } 3535 3536 static HRESULT WINAPI testinstance_GetClassID(IPersistFile *iface, CLSID *clsid) 3537 { 3538 ok(0, "unexpected call\n"); 3539 return E_NOTIMPL; 3540 } 3541 3542 static HRESULT WINAPI testinstance_IsDirty(IPersistFile *iface) 3543 { 3544 ok(0, "unexpected call\n"); 3545 return E_NOTIMPL; 3546 } 3547 3548 static HRESULT WINAPI testinstance_Load(IPersistFile *iface, LPCOLESTR filename, DWORD mode) 3549 { 3550 return g_persistfile_load_ret; 3551 } 3552 3553 static HRESULT WINAPI testinstance_Save(IPersistFile *iface, LPCOLESTR filename, BOOL remember) 3554 { 3555 return E_NOTIMPL; 3556 } 3557 3558 static HRESULT WINAPI testinstance_SaveCompleted(IPersistFile *iface, LPCOLESTR filename) 3559 { 3560 ok(0, "unexpected call\n"); 3561 return E_NOTIMPL; 3562 } 3563 3564 static HRESULT WINAPI testinstance_GetCurFile(IPersistFile *iface, LPOLESTR *filename) 3565 { 3566 ok(0, "unexpected call\n"); 3567 return E_NOTIMPL; 3568 } 3569 3570 static const IPersistFileVtbl testpersistfilevtbl = { 3571 testinstance_QI, 3572 testinstance_AddRef, 3573 testinstance_Release, 3574 testinstance_GetClassID, 3575 testinstance_IsDirty, 3576 testinstance_Load, 3577 testinstance_Save, 3578 testinstance_SaveCompleted, 3579 testinstance_GetCurFile 3580 }; 3581 3582 static IPersistFile testpersistfile = { &testpersistfilevtbl }; 3583 3584 static HRESULT WINAPI getinstance_cf_QI(IClassFactory *iface, REFIID riid, void **obj) 3585 { 3586 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) { 3587 *obj = iface; 3588 IClassFactory_AddRef(iface); 3589 return S_OK; 3590 } 3591 3592 *obj = NULL; 3593 return E_NOINTERFACE; 3594 } 3595 3596 static ULONG WINAPI getinstance_cf_AddRef(IClassFactory *iface) 3597 { 3598 return 2; 3599 } 3600 3601 static ULONG WINAPI getinstance_cf_Release(IClassFactory *iface) 3602 { 3603 return 1; 3604 } 3605 3606 static HRESULT WINAPI getinstance_cf_CreateInstance(IClassFactory *iface, IUnknown *outer, 3607 REFIID riid, void **obj) 3608 { 3609 if (IsEqualIID(riid, &IID_IUnknown)) { 3610 *obj = &testpersistfile; 3611 return S_OK; 3612 } 3613 3614 ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid)); 3615 *obj = NULL; 3616 return E_NOTIMPL; 3617 } 3618 3619 static HRESULT WINAPI getinstance_cf_LockServer(IClassFactory *iface, BOOL lock) 3620 { 3621 ok(0, "unexpected call\n"); 3622 return E_NOTIMPL; 3623 } 3624 3625 static const IClassFactoryVtbl getinstance_cf_vtbl = { 3626 getinstance_cf_QI, 3627 getinstance_cf_AddRef, 3628 getinstance_cf_Release, 3629 getinstance_cf_CreateInstance, 3630 getinstance_cf_LockServer 3631 }; 3632 3633 static IClassFactory getinstance_cf = { &getinstance_cf_vtbl }; 3634 3635 static void test_CoGetInstanceFromFile(void) 3636 { 3637 static const WCHAR filenameW[] = {'d','u','m','m','y','p','a','t','h',0}; 3638 CLSID *clsid = (CLSID*)&CLSID_testclsid; 3639 MULTI_QI mqi[2]; 3640 DWORD cookie; 3641 HRESULT hr; 3642 3643 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 3644 ok(hr == S_OK, "got 0x%08x\n", hr); 3645 3646 /* CLSID is not specified, file does not exist */ 3647 mqi[0].pIID = &IID_IUnknown; 3648 mqi[0].pItf = NULL; 3649 mqi[0].hr = E_NOTIMPL; 3650 hr = CoGetInstanceFromFile(NULL, NULL, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); 3651 todo_wine 3652 ok(hr == MK_E_CANTOPENFILE, "got 0x%08x\n", hr); 3653 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf); 3654 ok(mqi[0].hr == E_NOINTERFACE, "got 0x%08x\n", mqi[0].hr); 3655 3656 /* class is not available */ 3657 mqi[0].pIID = &IID_IUnknown; 3658 mqi[0].pItf = NULL; 3659 mqi[0].hr = E_NOTIMPL; 3660 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); 3661 ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr); 3662 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf); 3663 ok(mqi[0].hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", mqi[0].hr); 3664 3665 hr = CoRegisterClassObject(clsid, (IUnknown*)&getinstance_cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, 3666 &cookie); 3667 ok(hr == S_OK, "got 0x%08x\n", hr); 3668 3669 mqi[0].pIID = &IID_IUnknown; 3670 mqi[0].pItf = (void*)0xdeadbeef; 3671 mqi[0].hr = S_OK; 3672 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); 3673 todo_wine { 3674 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3675 ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf); 3676 } 3677 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr); 3678 3679 mqi[0].pIID = &IID_IUnknown; 3680 mqi[0].pItf = (void*)0xdeadbeef; 3681 mqi[0].hr = E_NOTIMPL; 3682 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); 3683 todo_wine { 3684 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3685 ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf); 3686 ok(mqi[0].hr == E_NOTIMPL, "got 0x%08x\n", mqi[0].hr); 3687 } 3688 mqi[0].pIID = &IID_IUnknown; 3689 mqi[0].pItf = NULL; 3690 mqi[0].hr = E_NOTIMPL; 3691 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); 3692 ok(hr == S_OK, "got 0x%08x\n", hr); 3693 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf); 3694 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr); 3695 3696 mqi[0].pIID = &IID_IUnknown; 3697 mqi[0].pItf = NULL; 3698 mqi[0].hr = S_OK; 3699 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); 3700 ok(hr == S_OK, "got 0x%08x\n", hr); 3701 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf); 3702 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr); 3703 3704 mqi[0].pIID = &IID_IUnknown; 3705 mqi[0].pItf = NULL; 3706 mqi[0].hr = S_OK; 3707 g_persistfile_qi_ret = S_FALSE; 3708 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); 3709 ok(hr == S_OK, "got 0x%08x\n", hr); 3710 ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf); 3711 ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr); 3712 g_persistfile_qi_ret = S_OK; 3713 3714 mqi[0].pIID = &IID_IUnknown; 3715 mqi[0].pItf = NULL; 3716 mqi[0].hr = S_OK; 3717 mqi[1].pIID = &IID_IUnknown; 3718 mqi[1].pItf = NULL; 3719 mqi[1].hr = S_OK; 3720 g_persistfile_qi_ret = 0x8000efef; 3721 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi); 3722 ok(hr == 0x8000efef, "got 0x%08x\n", hr); 3723 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf); 3724 ok(mqi[0].hr == 0x8000efef, "got 0x%08x\n", mqi[0].hr); 3725 ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf); 3726 ok(mqi[1].hr == 0x8000efef, "got 0x%08x\n", mqi[1].hr); 3727 g_persistfile_qi_ret = S_OK; 3728 3729 mqi[0].pIID = &IID_IUnknown; 3730 mqi[0].pItf = NULL; 3731 mqi[0].hr = S_OK; 3732 mqi[1].pIID = &IID_IUnknown; 3733 mqi[1].pItf = NULL; 3734 mqi[1].hr = S_OK; 3735 g_persistfile_load_ret = 0x8000fefe; 3736 hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi); 3737 ok(hr == 0x8000fefe, "got 0x%08x\n", hr); 3738 ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf); 3739 ok(mqi[0].hr == 0x8000fefe, "got 0x%08x\n", mqi[0].hr); 3740 ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf); 3741 ok(mqi[1].hr == 0x8000fefe, "got 0x%08x\n", mqi[1].hr); 3742 g_persistfile_load_ret = S_OK; 3743 3744 hr = CoRevokeClassObject(cookie); 3745 ok(hr == S_OK, "got 0x%08x\n", hr); 3746 3747 CoUninitialize(); 3748 } 3749 3750 static void test_GlobalOptions(void) 3751 { 3752 IGlobalOptions *global_options; 3753 HRESULT hres; 3754 3755 CoInitialize(NULL); 3756 3757 hres = CoCreateInstance(&CLSID_GlobalOptions, NULL, CLSCTX_INPROC_SERVER, 3758 &IID_IGlobalOptions, (void**)&global_options); 3759 ok(hres == S_OK || broken(hres == E_NOINTERFACE), "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres); 3760 if(FAILED(hres)) 3761 { 3762 win_skip("CLSID_GlobalOptions not available\n"); 3763 CoUninitialize(); 3764 return; 3765 } 3766 3767 IGlobalOptions_Release(global_options); 3768 3769 hres = CoCreateInstance(&CLSID_GlobalOptions, (IUnknown*)0xdeadbeef, CLSCTX_INPROC_SERVER, 3770 &IID_IGlobalOptions, (void**)&global_options); 3771 ok(hres == E_INVALIDARG, "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres); 3772 3773 CoUninitialize(); 3774 } 3775 3776 static void init_funcs(void) 3777 { 3778 HMODULE hOle32 = GetModuleHandleA("ole32"); 3779 HMODULE hAdvapi32 = GetModuleHandleA("advapi32"); 3780 HMODULE hkernel32 = GetModuleHandleA("kernel32"); 3781 3782 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext"); 3783 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext"); 3784 pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass"); 3785 pCoTreatAsClass = (void*)GetProcAddress(hOle32,"CoTreatAsClass"); 3786 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken"); 3787 pCoGetApartmentType = (void*)GetProcAddress(hOle32, "CoGetApartmentType"); 3788 pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA"); 3789 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey"); 3790 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"); 3791 3792 pActivateActCtx = (void*)GetProcAddress(hkernel32, "ActivateActCtx"); 3793 pCreateActCtxW = (void*)GetProcAddress(hkernel32, "CreateActCtxW"); 3794 pDeactivateActCtx = (void*)GetProcAddress(hkernel32, "DeactivateActCtx"); 3795 pIsWow64Process = (void*)GetProcAddress(hkernel32, "IsWow64Process"); 3796 pReleaseActCtx = (void*)GetProcAddress(hkernel32, "ReleaseActCtx"); 3797 } 3798 3799 static DWORD CALLBACK implicit_mta_proc(void *param) 3800 { 3801 IComThreadingInfo *threading_info; 3802 ULONG_PTR token; 3803 IUnknown *unk; 3804 DWORD cookie; 3805 CLSID clsid; 3806 HRESULT hr; 3807 3808 test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA); 3809 3810 hr = CoCreateInstance(&CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); 3811 ok_ole_success(hr, "CoCreateInstance"); 3812 IUnknown_Release(unk); 3813 3814 hr = CoGetClassObject(&CLSID_InternetZoneManager, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&unk); 3815 ok_ole_success(hr, "CoGetClassObject"); 3816 IUnknown_Release(unk); 3817 3818 hr = CoGetObjectContext(&IID_IComThreadingInfo, (void **)&threading_info); 3819 ok_ole_success(hr, "CoGetObjectContext"); 3820 IComThreadingInfo_Release(threading_info); 3821 3822 hr = CoGetContextToken(&token); 3823 ok_ole_success(hr, "CoGetContextToken"); 3824 3825 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer); 3826 ok_ole_success(hr, "CoRegisterPSClsid"); 3827 3828 hr = CoGetPSClsid(&IID_IClassFactory, &clsid); 3829 ok_ole_success(hr, "CoGetPSClsid"); 3830 3831 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, 3832 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); 3833 ok_ole_success(hr, "CoRegisterClassObject"); 3834 3835 hr = CoRevokeClassObject(cookie); 3836 ok_ole_success(hr, "CoRevokeClassObject"); 3837 3838 hr = CoRegisterMessageFilter(NULL, NULL); 3839 ok(hr == CO_E_NOT_SUPPORTED, "got %#x\n", hr); 3840 3841 hr = CoLockObjectExternal(&Test_Unknown, TRUE, TRUE); 3842 ok_ole_success(hr, "CoLockObjectExternal"); 3843 3844 hr = CoDisconnectObject(&Test_Unknown, 0); 3845 ok_ole_success(hr, "CoDisconnectObject"); 3846 3847 return 0; 3848 } 3849 3850 /* Some COM functions (perhaps even all of them?) can make use of an "implicit" 3851 * multi-threaded apartment created by another thread in the same process. */ 3852 static void test_implicit_mta(void) 3853 { 3854 HANDLE thread; 3855 3856 CoInitializeEx(NULL, COINIT_MULTITHREADED); 3857 3858 thread = CreateThread(NULL, 0, implicit_mta_proc, NULL, 0, NULL); 3859 ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); 3860 3861 CoUninitialize(); 3862 } 3863 3864 START_TEST(compobj) 3865 { 3866 init_funcs(); 3867 3868 if (!pCoInitializeEx) 3869 { 3870 trace("You need DCOM95 installed to run this test\n"); 3871 return; 3872 } 3873 3874 if (!pCreateActCtxW) 3875 win_skip("Activation contexts are not supported, some tests will be skipped.\n"); 3876 3877 test_ProgIDFromCLSID(); 3878 test_CLSIDFromProgID(); 3879 test_CLSIDFromString(); 3880 test_IIDFromString(); 3881 test_StringFromGUID2(); 3882 test_CoCreateInstance(); 3883 test_ole_menu(); 3884 test_CoGetClassObject(); 3885 test_CoCreateInstanceEx(); 3886 test_CoRegisterMessageFilter(); 3887 test_CoRegisterPSClsid(); 3888 test_CoGetPSClsid(); 3889 test_CoUnmarshalInterface(); 3890 test_CoGetInterfaceAndReleaseStream(); 3891 test_CoMarshalInterface(); 3892 test_CoMarshalInterThreadInterfaceInStream(); 3893 test_CoRegisterClassObject(); 3894 test_registered_object_thread_affinity(); 3895 test_CoFreeUnusedLibraries(); 3896 test_CoGetObjectContext(); 3897 test_CoGetCallContext(); 3898 test_CoGetContextToken(); 3899 test_TreatAsClass(); 3900 test_CoInitializeEx(); 3901 test_OleInitialize_InitCounting(); 3902 test_OleRegGetMiscStatus(); 3903 test_CoCreateGuid(); 3904 test_CoWaitForMultipleHandles(); 3905 test_CoGetMalloc(); 3906 test_OleRegGetUserType(); 3907 test_CoGetApartmentType(); 3908 test_IMallocSpy(); 3909 test_CoGetCurrentLogicalThreadId(); 3910 test_IInitializeSpy(FALSE); 3911 test_IInitializeSpy(TRUE); 3912 test_CoGetInstanceFromFile(); 3913 test_GlobalOptions(); 3914 test_implicit_mta(); 3915 } 3916