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