1 /* 2 * Moniker Tests 3 * 4 * Copyright 2004 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 <comcat.h> 24 #include <olectl.h> 25 26 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks) 27 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks) 28 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr) 29 #define COUNTOF(x) (sizeof(x) / sizeof(x[0])) 30 31 #define CHECK_EXPECTED_METHOD(method_name) \ 32 do { \ 33 trace("%s\n", method_name); \ 34 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \ 35 if (*expected_method_list) \ 36 { \ 37 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \ 38 *expected_method_list, method_name); \ 39 expected_method_list++; \ 40 } \ 41 } while(0) 42 43 static char const * const *expected_method_list; 44 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0}; 45 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0}; 46 47 static const CLSID CLSID_TestMoniker = 48 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */ 49 0xb306bfbc, 50 0x496e, 51 0x4f53, 52 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7} 53 }; 54 55 static LONG cLocks; 56 57 static void LockModule(void) 58 { 59 InterlockedIncrement(&cLocks); 60 } 61 62 static void UnlockModule(void) 63 { 64 InterlockedDecrement(&cLocks); 65 } 66 67 static SIZE_T round_global_size(SIZE_T size) 68 { 69 static SIZE_T global_size_alignment = -1; 70 if (global_size_alignment == -1) 71 { 72 void *p = GlobalAlloc(GMEM_FIXED, 1); 73 global_size_alignment = GlobalSize(p); 74 GlobalFree(p); 75 } 76 77 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1)); 78 } 79 80 static DWORD external_connections; 81 82 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv) 83 { 84 ok(0, "unexpected call\n"); 85 *ppv = NULL; 86 return E_NOINTERFACE; 87 } 88 89 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface) 90 { 91 return 2; 92 } 93 94 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface) 95 { 96 return 1; 97 } 98 99 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved) 100 { 101 trace("add connection\n"); 102 103 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn); 104 ok(!reserved, "reserved = %x\n", reserved); 105 return ++external_connections; 106 } 107 108 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn, 109 DWORD reserved, BOOL fLastReleaseCloses) 110 { 111 trace("release connection\n"); 112 113 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn); 114 ok(!reserved, "reserved = %x\n", reserved); 115 116 return --external_connections; 117 } 118 119 static const IExternalConnectionVtbl ExternalConnectionVtbl = { 120 ExternalConnection_QueryInterface, 121 ExternalConnection_AddRef, 122 ExternalConnection_Release, 123 ExternalConnection_AddConnection, 124 ExternalConnection_ReleaseConnection 125 }; 126 127 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl }; 128 129 static HRESULT WINAPI Test_IClassFactory_QueryInterface( 130 LPCLASSFACTORY iface, 131 REFIID riid, 132 LPVOID *ppvObj) 133 { 134 if (ppvObj == NULL) return E_POINTER; 135 136 if (IsEqualGUID(riid, &IID_IUnknown) || 137 IsEqualGUID(riid, &IID_IClassFactory)) 138 { 139 *ppvObj = iface; 140 IClassFactory_AddRef(iface); 141 return S_OK; 142 } 143 144 if(IsEqualGUID(riid, &IID_IExternalConnection)) { 145 *ppvObj = &ExternalConnection; 146 return S_OK; 147 } 148 149 *ppvObj = NULL; 150 return E_NOINTERFACE; 151 } 152 153 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface) 154 { 155 LockModule(); 156 return 2; /* non-heap-based object */ 157 } 158 159 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface) 160 { 161 UnlockModule(); 162 return 1; /* non-heap-based object */ 163 } 164 165 static HRESULT WINAPI Test_IClassFactory_CreateInstance( 166 LPCLASSFACTORY iface, 167 LPUNKNOWN pUnkOuter, 168 REFIID riid, 169 LPVOID *ppvObj) 170 { 171 return E_NOTIMPL; 172 } 173 174 static HRESULT WINAPI Test_IClassFactory_LockServer( 175 LPCLASSFACTORY iface, 176 BOOL fLock) 177 { 178 return S_OK; 179 } 180 181 static const IClassFactoryVtbl TestClassFactory_Vtbl = 182 { 183 Test_IClassFactory_QueryInterface, 184 Test_IClassFactory_AddRef, 185 Test_IClassFactory_Release, 186 Test_IClassFactory_CreateInstance, 187 Test_IClassFactory_LockServer 188 }; 189 190 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl }; 191 192 typedef struct 193 { 194 IUnknown IUnknown_iface; 195 ULONG refs; 196 } HeapUnknown; 197 198 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface) 199 { 200 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface); 201 } 202 203 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 204 { 205 if (IsEqualIID(riid, &IID_IUnknown)) 206 { 207 IUnknown_AddRef(iface); 208 *ppv = iface; 209 return S_OK; 210 } 211 *ppv = NULL; 212 return E_NOINTERFACE; 213 } 214 215 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface) 216 { 217 HeapUnknown *This = impl_from_IUnknown(iface); 218 return InterlockedIncrement((LONG*)&This->refs); 219 } 220 221 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface) 222 { 223 HeapUnknown *This = impl_from_IUnknown(iface); 224 ULONG refs = InterlockedDecrement((LONG*)&This->refs); 225 if (!refs) HeapFree(GetProcessHeap(), 0, This); 226 return refs; 227 } 228 229 static const IUnknownVtbl HeapUnknown_Vtbl = 230 { 231 HeapUnknown_QueryInterface, 232 HeapUnknown_AddRef, 233 HeapUnknown_Release 234 }; 235 236 static HRESULT WINAPI 237 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) 238 { 239 if (!ppvObject) 240 return E_INVALIDARG; 241 242 *ppvObject = 0; 243 244 if (IsEqualIID(&IID_IUnknown, riid) || 245 IsEqualIID(&IID_IPersist, riid) || 246 IsEqualIID(&IID_IPersistStream,riid) || 247 IsEqualIID(&IID_IMoniker, riid)) 248 *ppvObject = iface; 249 if (IsEqualIID(&IID_IROTData, riid)) 250 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)"); 251 252 if ((*ppvObject)==0) 253 return E_NOINTERFACE; 254 255 IMoniker_AddRef(iface); 256 257 return S_OK; 258 } 259 260 static ULONG WINAPI 261 Moniker_AddRef(IMoniker* iface) 262 { 263 return 2; 264 } 265 266 static ULONG WINAPI 267 Moniker_Release(IMoniker* iface) 268 { 269 return 1; 270 } 271 272 static HRESULT WINAPI 273 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID) 274 { 275 CHECK_EXPECTED_METHOD("Moniker_GetClassID"); 276 277 *pClassID = CLSID_TestMoniker; 278 279 return S_OK; 280 } 281 282 static HRESULT WINAPI 283 Moniker_IsDirty(IMoniker* iface) 284 { 285 CHECK_EXPECTED_METHOD("Moniker_IsDirty"); 286 287 return S_FALSE; 288 } 289 290 static HRESULT WINAPI 291 Moniker_Load(IMoniker* iface, IStream* pStm) 292 { 293 CHECK_EXPECTED_METHOD("Moniker_Load"); 294 return E_NOTIMPL; 295 } 296 297 static HRESULT WINAPI 298 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty) 299 { 300 CHECK_EXPECTED_METHOD("Moniker_Save"); 301 return E_NOTIMPL; 302 } 303 304 static HRESULT WINAPI 305 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize) 306 { 307 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax"); 308 return E_NOTIMPL; 309 } 310 311 static HRESULT WINAPI 312 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 313 REFIID riid, VOID** ppvResult) 314 { 315 CHECK_EXPECTED_METHOD("Moniker_BindToObject"); 316 return E_NOTIMPL; 317 } 318 319 static HRESULT WINAPI 320 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 321 REFIID riid, VOID** ppvObject) 322 { 323 CHECK_EXPECTED_METHOD("Moniker_BindToStorage"); 324 return E_NOTIMPL; 325 } 326 327 static HRESULT WINAPI 328 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar, 329 IMoniker** ppmkToLeft, IMoniker** ppmkReduced) 330 { 331 CHECK_EXPECTED_METHOD("Moniker_Reduce"); 332 333 if (ppmkReduced==NULL) 334 return E_POINTER; 335 336 IMoniker_AddRef(iface); 337 338 *ppmkReduced=iface; 339 340 return MK_S_REDUCED_TO_SELF; 341 } 342 343 static HRESULT WINAPI 344 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight, 345 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) 346 { 347 CHECK_EXPECTED_METHOD("Moniker_ComposeWith"); 348 return E_NOTIMPL; 349 } 350 351 static HRESULT WINAPI 352 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) 353 { 354 CHECK_EXPECTED_METHOD("Moniker_Enum"); 355 356 if (ppenumMoniker == NULL) 357 return E_POINTER; 358 359 *ppenumMoniker = NULL; 360 361 return S_OK; 362 } 363 364 static HRESULT WINAPI 365 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) 366 { 367 CHECK_EXPECTED_METHOD("Moniker_IsEqual"); 368 return E_NOTIMPL; 369 } 370 371 static HRESULT WINAPI 372 Moniker_Hash(IMoniker* iface,DWORD* pdwHash) 373 { 374 CHECK_EXPECTED_METHOD("Moniker_Hash"); 375 return E_NOTIMPL; 376 } 377 378 static HRESULT WINAPI 379 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 380 IMoniker* pmkNewlyRunning) 381 { 382 CHECK_EXPECTED_METHOD("Moniker_IsRunning"); 383 return E_NOTIMPL; 384 } 385 386 static HRESULT WINAPI 387 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, 388 IMoniker* pmkToLeft, FILETIME* pFileTime) 389 { 390 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange"); 391 return E_NOTIMPL; 392 } 393 394 static HRESULT WINAPI 395 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk) 396 { 397 CHECK_EXPECTED_METHOD("Moniker_Inverse"); 398 return E_NOTIMPL; 399 } 400 401 static HRESULT WINAPI 402 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) 403 { 404 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith"); 405 return E_NOTIMPL; 406 } 407 408 static HRESULT WINAPI 409 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) 410 { 411 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo"); 412 return E_NOTIMPL; 413 } 414 415 static HRESULT WINAPI 416 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc, 417 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) 418 { 419 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0}; 420 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName"); 421 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszDisplayName)); 422 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName)); 423 return S_OK; 424 } 425 426 static HRESULT WINAPI 427 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 428 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut) 429 { 430 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName"); 431 return E_NOTIMPL; 432 } 433 434 static HRESULT WINAPI 435 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) 436 { 437 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker"); 438 439 if (!pwdMksys) 440 return E_POINTER; 441 442 (*pwdMksys)=MKSYS_NONE; 443 444 return S_FALSE; 445 } 446 447 static const IMonikerVtbl MonikerNoROTDataVtbl = 448 { 449 MonikerNoROTData_QueryInterface, 450 Moniker_AddRef, 451 Moniker_Release, 452 Moniker_GetClassID, 453 Moniker_IsDirty, 454 Moniker_Load, 455 Moniker_Save, 456 Moniker_GetSizeMax, 457 Moniker_BindToObject, 458 Moniker_BindToStorage, 459 Moniker_Reduce, 460 Moniker_ComposeWith, 461 Moniker_Enum, 462 Moniker_IsEqual, 463 Moniker_Hash, 464 Moniker_IsRunning, 465 Moniker_GetTimeOfLastChange, 466 Moniker_Inverse, 467 Moniker_CommonPrefixWith, 468 Moniker_RelativePathTo, 469 Moniker_GetDisplayName, 470 Moniker_ParseDisplayName, 471 Moniker_IsSystemMoniker 472 }; 473 474 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl }; 475 476 static IMoniker Moniker; 477 478 static HRESULT WINAPI 479 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) 480 { 481 return IMoniker_QueryInterface(&Moniker, riid, ppvObject); 482 } 483 484 static ULONG WINAPI 485 ROTData_AddRef(IROTData *iface) 486 { 487 return 2; 488 } 489 490 static ULONG WINAPI 491 ROTData_Release(IROTData* iface) 492 { 493 return 1; 494 } 495 496 static HRESULT WINAPI 497 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData, 498 ULONG cbMax, ULONG* pcbData) 499 { 500 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData"); 501 502 *pcbData = 1; 503 if (cbMax < *pcbData) 504 return E_OUTOFMEMORY; 505 506 *pbData = 0xde; 507 508 return S_OK; 509 } 510 511 static IROTDataVtbl ROTDataVtbl = 512 { 513 ROTData_QueryInterface, 514 ROTData_AddRef, 515 ROTData_Release, 516 ROTData_GetComparisonData 517 }; 518 519 static IROTData ROTData = { &ROTDataVtbl }; 520 521 static HRESULT WINAPI 522 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) 523 { 524 if (!ppvObject) 525 return E_INVALIDARG; 526 527 *ppvObject = 0; 528 529 if (IsEqualIID(&IID_IUnknown, riid) || 530 IsEqualIID(&IID_IPersist, riid) || 531 IsEqualIID(&IID_IPersistStream,riid) || 532 IsEqualIID(&IID_IMoniker, riid)) 533 *ppvObject = iface; 534 if (IsEqualIID(&IID_IROTData, riid)) 535 { 536 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)"); 537 *ppvObject = &ROTData; 538 } 539 540 if ((*ppvObject)==0) 541 return E_NOINTERFACE; 542 543 IMoniker_AddRef(iface); 544 545 return S_OK; 546 } 547 548 static const IMonikerVtbl MonikerVtbl = 549 { 550 Moniker_QueryInterface, 551 Moniker_AddRef, 552 Moniker_Release, 553 Moniker_GetClassID, 554 Moniker_IsDirty, 555 Moniker_Load, 556 Moniker_Save, 557 Moniker_GetSizeMax, 558 Moniker_BindToObject, 559 Moniker_BindToStorage, 560 Moniker_Reduce, 561 Moniker_ComposeWith, 562 Moniker_Enum, 563 Moniker_IsEqual, 564 Moniker_Hash, 565 Moniker_IsRunning, 566 Moniker_GetTimeOfLastChange, 567 Moniker_Inverse, 568 Moniker_CommonPrefixWith, 569 Moniker_RelativePathTo, 570 Moniker_GetDisplayName, 571 Moniker_ParseDisplayName, 572 Moniker_IsSystemMoniker 573 }; 574 575 static IMoniker Moniker = { &MonikerVtbl }; 576 577 static void test_ROT(void) 578 { 579 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-', 580 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-', 581 '2','0','4','6','E','5','8','6','C','9','2','5',0}; 582 HRESULT hr; 583 IMoniker *pMoniker = NULL; 584 IRunningObjectTable *pROT = NULL; 585 DWORD dwCookie; 586 static const char *methods_register_no_ROTData[] = 587 { 588 "Moniker_Reduce", 589 "Moniker_GetTimeOfLastChange", 590 "Moniker_QueryInterface(IID_IROTData)", 591 "Moniker_GetDisplayName", 592 "Moniker_GetClassID", 593 NULL 594 }; 595 static const char *methods_register[] = 596 { 597 "Moniker_Reduce", 598 "Moniker_GetTimeOfLastChange", 599 "Moniker_QueryInterface(IID_IROTData)", 600 "ROTData_GetComparisonData", 601 NULL 602 }; 603 static const char *methods_isrunning_no_ROTData[] = 604 { 605 "Moniker_Reduce", 606 "Moniker_QueryInterface(IID_IROTData)", 607 "Moniker_GetDisplayName", 608 "Moniker_GetClassID", 609 NULL 610 }; 611 static const char *methods_isrunning[] = 612 { 613 "Moniker_Reduce", 614 "Moniker_QueryInterface(IID_IROTData)", 615 "ROTData_GetComparisonData", 616 NULL 617 }; 618 619 cLocks = 0; 620 621 hr = GetRunningObjectTable(0, &pROT); 622 ok_ole_success(hr, GetRunningObjectTable); 623 624 expected_method_list = methods_register_no_ROTData; 625 external_connections = 0; 626 /* try with our own moniker that doesn't support IROTData */ 627 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE, 628 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie); 629 ok_ole_success(hr, IRunningObjectTable_Register); 630 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list); 631 ok(external_connections == 1, "external_connections = %d\n", external_connections); 632 633 ok_more_than_one_lock(); 634 635 expected_method_list = methods_isrunning_no_ROTData; 636 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData); 637 ok_ole_success(hr, IRunningObjectTable_IsRunning); 638 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list); 639 640 hr = IRunningObjectTable_Revoke(pROT, dwCookie); 641 ok_ole_success(hr, IRunningObjectTable_Revoke); 642 ok(external_connections == 0, "external_connections = %d\n", external_connections); 643 644 ok_no_locks(); 645 646 expected_method_list = methods_register; 647 /* try with our own moniker */ 648 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE, 649 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie); 650 ok_ole_success(hr, IRunningObjectTable_Register); 651 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list); 652 653 ok_more_than_one_lock(); 654 655 expected_method_list = methods_isrunning; 656 hr = IRunningObjectTable_IsRunning(pROT, &Moniker); 657 ok_ole_success(hr, IRunningObjectTable_IsRunning); 658 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list); 659 660 hr = IRunningObjectTable_Revoke(pROT, dwCookie); 661 ok_ole_success(hr, IRunningObjectTable_Revoke); 662 663 ok_no_locks(); 664 665 hr = CreateFileMoniker(wszFileName, &pMoniker); 666 ok_ole_success(hr, CreateClassMoniker); 667 668 /* test flags: 0 */ 669 external_connections = 0; 670 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory, 671 pMoniker, &dwCookie); 672 ok_ole_success(hr, IRunningObjectTable_Register); 673 ok(external_connections == 0, "external_connections = %d\n", external_connections); 674 675 ok_more_than_one_lock(); 676 677 hr = IRunningObjectTable_Revoke(pROT, dwCookie); 678 ok_ole_success(hr, IRunningObjectTable_Revoke); 679 680 ok_no_locks(); 681 682 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */ 683 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE, 684 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie); 685 ok_ole_success(hr, IRunningObjectTable_Register); 686 687 ok_more_than_one_lock(); 688 689 hr = IRunningObjectTable_Revoke(pROT, dwCookie); 690 ok_ole_success(hr, IRunningObjectTable_Revoke); 691 692 ok_no_locks(); 693 694 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */ 695 /* only succeeds when process is started by SCM and has LocalService 696 * or RunAs AppId values */ 697 hr = IRunningObjectTable_Register(pROT, 698 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT, 699 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie); 700 todo_wine { 701 ok(hr == CO_E_WRONG_SERVER_IDENTITY || 702 broken(hr == S_OK) /* Win9x */, 703 "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr); 704 } 705 if (hr == S_OK) IRunningObjectTable_Revoke(pROT, dwCookie); 706 707 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef, 708 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie); 709 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr); 710 711 IMoniker_Release(pMoniker); 712 713 IRunningObjectTable_Release(pROT); 714 } 715 716 static void test_ROT_multiple_entries(void) 717 { 718 HRESULT hr; 719 IMoniker *pMoniker = NULL; 720 IRunningObjectTable *pROT = NULL; 721 DWORD dwCookie1, dwCookie2; 722 IUnknown *pObject = NULL; 723 static const WCHAR moniker_path[] = 724 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0}; 725 726 hr = GetRunningObjectTable(0, &pROT); 727 ok_ole_success(hr, GetRunningObjectTable); 728 729 hr = CreateFileMoniker(moniker_path, &pMoniker); 730 ok_ole_success(hr, CreateFileMoniker); 731 732 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie1); 733 ok_ole_success(hr, IRunningObjectTable_Register); 734 735 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie2); 736 ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr); 737 738 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1); 739 740 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject); 741 ok_ole_success(hr, IRunningObjectTable_GetObject); 742 IUnknown_Release(pObject); 743 744 hr = IRunningObjectTable_Revoke(pROT, dwCookie1); 745 ok_ole_success(hr, IRunningObjectTable_Revoke); 746 747 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject); 748 ok_ole_success(hr, IRunningObjectTable_GetObject); 749 IUnknown_Release(pObject); 750 751 hr = IRunningObjectTable_Revoke(pROT, dwCookie2); 752 ok_ole_success(hr, IRunningObjectTable_Revoke); 753 754 IMoniker_Release(pMoniker); 755 756 IRunningObjectTable_Release(pROT); 757 } 758 759 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv) 760 { 761 if (IsEqualIID(riid, &IID_IUnknown) || 762 IsEqualIID(riid, &IID_IParseDisplayName)) 763 { 764 *ppv = iface; 765 IParseDisplayName_AddRef(iface); 766 return S_OK; 767 } 768 *ppv = NULL; 769 return E_NOINTERFACE; 770 } 771 772 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface) 773 { 774 return 2; 775 } 776 777 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface) 778 { 779 return 1; 780 } 781 782 static LPCWSTR expected_display_name; 783 784 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface, 785 IBindCtx *pbc, 786 LPOLESTR pszDisplayName, 787 ULONG *pchEaten, 788 IMoniker **ppmkOut) 789 { 790 char display_nameA[256]; 791 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL); 792 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA); 793 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n"); 794 *pchEaten = lstrlenW(pszDisplayName); 795 return CreateAntiMoniker(ppmkOut); 796 } 797 798 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl = 799 { 800 ParseDisplayName_QueryInterface, 801 ParseDisplayName_AddRef, 802 ParseDisplayName_Release, 803 ParseDisplayName_ParseDisplayName 804 }; 805 806 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl }; 807 808 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM) 809 { 810 IMoniker * spMoniker; 811 int monCnt=0, matchCnt=0; 812 813 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK)) 814 { 815 HRESULT hr; 816 WCHAR * szDisplayn; 817 monCnt++; 818 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn); 819 if (SUCCEEDED(hr)) 820 { 821 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2)) 822 matchCnt++; 823 CoTaskMemFree(szDisplayn); 824 } 825 } 826 trace("Total number of monikers is %i\n", monCnt); 827 return matchCnt; 828 } 829 830 static void test_MkParseDisplayName(void) 831 { 832 IBindCtx * pbc = NULL; 833 HRESULT hr; 834 IMoniker * pmk = NULL; 835 IMoniker * pmk1 = NULL; 836 IMoniker * pmk2 = NULL; 837 ULONG eaten; 838 int matchCnt; 839 IUnknown * object = NULL; 840 841 IUnknown *lpEM1; 842 843 IEnumMoniker *spEM1 = NULL; 844 IEnumMoniker *spEM2 = NULL; 845 IEnumMoniker *spEM3 = NULL; 846 847 DWORD pdwReg1=0; 848 DWORD grflags=0; 849 DWORD pdwReg2=0; 850 DWORD moniker_type; 851 IRunningObjectTable * pprot=NULL; 852 853 /* CLSID of My Computer */ 854 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':', 855 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D',':',0}; 856 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0}; 857 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0}; 858 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0}; 859 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0}; 860 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0}; 861 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0}; 862 static const WCHAR wszEmpty[] = {0}; 863 char szDisplayNameFile[256]; 864 WCHAR wszDisplayNameFile[256]; 865 int i, len; 866 867 const struct 868 { 869 LPBC *ppbc; 870 LPCOLESTR szDisplayName; 871 LPDWORD pchEaten; 872 LPMONIKER *ppmk; 873 } invalid_parameters[] = 874 { 875 {NULL, NULL, NULL, NULL}, 876 {NULL, NULL, NULL, &pmk}, 877 {NULL, NULL, &eaten, NULL}, 878 {NULL, NULL, &eaten, &pmk}, 879 {NULL, wszEmpty, NULL, NULL}, 880 {NULL, wszEmpty, NULL, &pmk}, 881 {NULL, wszEmpty, &eaten, NULL}, 882 {NULL, wszEmpty, &eaten, &pmk}, 883 {&pbc, NULL, NULL, NULL}, 884 {&pbc, NULL, NULL, &pmk}, 885 {&pbc, NULL, &eaten, NULL}, 886 {&pbc, NULL, &eaten, &pmk}, 887 {&pbc, wszEmpty, NULL, NULL}, 888 {&pbc, wszEmpty, NULL, &pmk}, 889 {&pbc, wszEmpty, &eaten, NULL}, 890 {&pbc, wszEmpty, &eaten, &pmk}, 891 }; 892 893 hr = CreateBindCtx(0, &pbc); 894 ok_ole_success(hr, CreateBindCtx); 895 896 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++) 897 { 898 eaten = 0xdeadbeef; 899 pmk = (IMoniker *)0xdeadbeef; 900 hr = MkParseDisplayName(invalid_parameters[i].ppbc ? *invalid_parameters[i].ppbc : NULL, 901 invalid_parameters[i].szDisplayName, 902 invalid_parameters[i].pchEaten, 903 invalid_parameters[i].ppmk); 904 ok(hr == E_INVALIDARG, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i, hr); 905 ok(eaten == 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i, eaten); 906 ok(pmk == (IMoniker *)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i, pmk); 907 } 908 909 eaten = 0xdeadbeef; 910 pmk = (IMoniker *)0xdeadbeef; 911 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk); 912 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */, 913 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr); 914 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten); 915 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk); 916 917 /* no special handling of "clsid:" without the string form of the clsid 918 * following */ 919 eaten = 0xdeadbeef; 920 pmk = (IMoniker *)0xdeadbeef; 921 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk); 922 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */, 923 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr); 924 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten); 925 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk); 926 927 /* shows clsid has higher precedence than a running object */ 928 hr = CreateFileMoniker(wszDisplayName, &pmk); 929 ok_ole_success(hr, CreateFileMoniker); 930 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot); 931 ok_ole_success(hr, IBindCtx_GetRunningObjectTable); 932 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1); 933 ok_ole_success(hr, IRunningObjectTable_Register); 934 IMoniker_Release(pmk); 935 pmk = NULL; 936 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk); 937 ok_ole_success(hr, MkParseDisplayName); 938 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1, 939 "Processed character count should have been 43 instead of %u\n", eaten); 940 if (pmk) 941 { 942 IMoniker_IsSystemMoniker(pmk, &moniker_type); 943 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type); 944 IMoniker_Release(pmk); 945 } 946 hr = IRunningObjectTable_Revoke(pprot, pdwReg1); 947 ok_ole_success(hr, IRunningObjectTable_Revoke); 948 IRunningObjectTable_Release(pprot); 949 950 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk); 951 ok_ole_success(hr, CreateFileMoniker); 952 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot); 953 ok_ole_success(hr, IBindCtx_GetRunningObjectTable); 954 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1); 955 ok_ole_success(hr, IRunningObjectTable_Register); 956 IMoniker_Release(pmk); 957 pmk = NULL; 958 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk); 959 ok_ole_success(hr, MkParseDisplayName); 960 ok(eaten == sizeof(wszDisplayNameRunning)/sizeof(WCHAR) - 1, 961 "Processed character count should have been 15 instead of %u\n", eaten); 962 if (pmk) 963 { 964 IMoniker_IsSystemMoniker(pmk, &moniker_type); 965 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type); 966 IMoniker_Release(pmk); 967 } 968 hr = IRunningObjectTable_Revoke(pprot, pdwReg1); 969 ok_ole_success(hr, IRunningObjectTable_Revoke); 970 IRunningObjectTable_Release(pprot); 971 972 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1); 973 ok_ole_success(hr, CoRegisterClassObject); 974 975 expected_display_name = wszDisplayNameProgId1; 976 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk); 977 ok_ole_success(hr, MkParseDisplayName); 978 ok(eaten == sizeof(wszDisplayNameProgId1)/sizeof(WCHAR) - 1, 979 "Processed character count should have been 8 instead of %u\n", eaten); 980 if (pmk) 981 { 982 IMoniker_IsSystemMoniker(pmk, &moniker_type); 983 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type); 984 IMoniker_Release(pmk); 985 } 986 987 expected_display_name = wszDisplayNameProgId2; 988 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk); 989 ok_ole_success(hr, MkParseDisplayName); 990 ok(eaten == sizeof(wszDisplayNameProgId2)/sizeof(WCHAR) - 1, 991 "Processed character count should have been 8 instead of %u\n", eaten); 992 if (pmk) 993 { 994 IMoniker_IsSystemMoniker(pmk, &moniker_type); 995 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type); 996 IMoniker_Release(pmk); 997 } 998 999 eaten = 0xdeadbeef; 1000 pmk = (IMoniker *)0xdeadbeef; 1001 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk); 1002 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */, 1003 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr); 1004 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten); 1005 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk); 1006 1007 hr = CoRevokeClassObject(pdwReg1); 1008 ok_ole_success(hr, CoRevokeClassObject); 1009 1010 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile)); 1011 strcat(szDisplayNameFile, "\\kernel32.dll"); 1012 len = MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0])); 1013 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk); 1014 ok_ole_success(hr, MkParseDisplayName); 1015 ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten); 1016 if (pmk) 1017 { 1018 IMoniker_IsSystemMoniker(pmk, &moniker_type); 1019 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type); 1020 IMoniker_Release(pmk); 1021 } 1022 1023 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk); 1024 ok_ole_success(hr, MkParseDisplayName); 1025 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1, "Processed character count should have been 43 instead of %u\n", eaten); 1026 1027 if (pmk) 1028 { 1029 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object); 1030 ok_ole_success(hr, IMoniker_BindToObject); 1031 1032 if (SUCCEEDED(hr)) 1033 IUnknown_Release(object); 1034 IMoniker_Release(pmk); 1035 } 1036 IBindCtx_Release(pbc); 1037 1038 /* Test the EnumMoniker interface */ 1039 hr = CreateBindCtx(0, &pbc); 1040 ok_ole_success(hr, CreateBindCtx); 1041 1042 hr = CreateFileMoniker(wszFileName1, &pmk1); 1043 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr); 1044 hr = CreateFileMoniker(wszFileName2, &pmk2); 1045 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr); 1046 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot); 1047 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr); 1048 1049 /* Check EnumMoniker before registering */ 1050 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1); 1051 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr); 1052 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1); 1053 /* Register a couple of Monikers and check is ok */ 1054 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1); 1055 1056 matchCnt = count_moniker_matches(pbc, spEM1); 1057 trace("Number of matches is %i\n", matchCnt); 1058 1059 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE; 1060 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1); 1061 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", 1062 hr, pprot, grflags, lpEM1, pmk1, pdwReg1); 1063 1064 trace("IROT::Register\n"); 1065 grflags=0; 1066 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE; 1067 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2); 1068 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr, 1069 pprot, grflags, lpEM1, pmk2, pdwReg2); 1070 1071 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2); 1072 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr); 1073 1074 matchCnt = count_moniker_matches(pbc, spEM2); 1075 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt); 1076 1077 trace("IEnumMoniker::Clone\n"); 1078 IEnumMoniker_Clone(spEM2, &spEM3); 1079 1080 matchCnt = count_moniker_matches(pbc, spEM3); 1081 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt); 1082 trace("IEnumMoniker::Reset\n"); 1083 IEnumMoniker_Reset(spEM3); 1084 1085 matchCnt = count_moniker_matches(pbc, spEM3); 1086 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt); 1087 1088 IRunningObjectTable_Revoke(pprot,pdwReg1); 1089 IRunningObjectTable_Revoke(pprot,pdwReg2); 1090 IUnknown_Release(lpEM1); 1091 IEnumMoniker_Release(spEM1); 1092 IEnumMoniker_Release(spEM2); 1093 IEnumMoniker_Release(spEM3); 1094 IMoniker_Release(pmk1); 1095 IMoniker_Release(pmk2); 1096 IRunningObjectTable_Release(pprot); 1097 1098 IBindCtx_Release(pbc); 1099 } 1100 1101 static const LARGE_INTEGER llZero; 1102 1103 static const BYTE expected_class_moniker_marshal_data[] = 1104 { 1105 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00, 1106 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1107 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1108 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1109 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1110 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00, 1111 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00, 1112 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1113 0x00,0x00,0x00,0x00, 1114 }; 1115 1116 static const BYTE expected_class_moniker_saved_data[] = 1117 { 1118 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00, 1119 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1120 0x00,0x00,0x00,0x00, 1121 }; 1122 1123 static const BYTE expected_class_moniker_comparison_data[] = 1124 { 1125 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1126 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1127 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00, 1128 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1129 }; 1130 1131 static const WCHAR expected_class_moniker_display_name[] = 1132 { 1133 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0', 1134 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0', 1135 '0','0','0','0','4','6',':',0 1136 }; 1137 1138 static const BYTE expected_item_moniker_comparison_data[] = 1139 { 1140 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1141 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1142 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00, 1143 0x54,0x00,0x00,0x00, 1144 }; 1145 1146 static const BYTE expected_item_moniker_saved_data[] = 1147 { 1148 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00, 1149 0x00,0x00,0x54,0x65,0x73,0x74,0x00, 1150 }; 1151 1152 static const BYTE expected_item_moniker_marshal_data[] = 1153 { 1154 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00, 1155 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1156 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1157 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1158 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1159 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00, 1160 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00, 1161 0x00,0x00,0x54,0x65,0x73,0x74,0x00, 1162 }; 1163 1164 static const BYTE expected_anti_moniker_marshal_data[] = 1165 { 1166 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00, 1167 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1168 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1169 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1170 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1171 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00, 1172 0x01,0x00,0x00,0x00, 1173 }; 1174 1175 static const BYTE expected_anti_moniker_saved_data[] = 1176 { 1177 0x01,0x00,0x00,0x00, 1178 }; 1179 1180 static const BYTE expected_anti_moniker_comparison_data[] = 1181 { 1182 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1183 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1184 0x01,0x00,0x00,0x00, 1185 }; 1186 1187 static const BYTE expected_gc_moniker_marshal_data[] = 1188 { 1189 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00, 1190 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1191 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1192 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1193 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1194 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00, 1195 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00, 1196 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1197 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1198 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1199 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1200 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00, 1201 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00, 1202 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d, 1203 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f, 1204 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, 1205 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04, 1206 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, 1207 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00, 1208 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02, 1209 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00, 1210 0x00,0x57,0x69,0x6e,0x65,0x00, 1211 }; 1212 1213 static const BYTE expected_gc_moniker_saved_data[] = 1214 { 1215 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00, 1216 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, 1217 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00, 1218 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65, 1219 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00, 1220 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00, 1221 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23, 1222 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e, 1223 0x65,0x00, 1224 }; 1225 1226 static const BYTE expected_gc_moniker_comparison_data[] = 1227 { 1228 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1229 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1230 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 1231 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 1232 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00, 1233 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00, 1234 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, 1235 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00, 1236 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00, 1237 }; 1238 1239 static void test_moniker( 1240 const char *testname, IMoniker *moniker, 1241 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data, 1242 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data, 1243 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data, 1244 LPCWSTR expected_display_name) 1245 { 1246 IStream * stream; 1247 IROTData * rotdata; 1248 HRESULT hr; 1249 HGLOBAL hglobal; 1250 LPBYTE moniker_data; 1251 DWORD moniker_size; 1252 DWORD i; 1253 BOOL same; 1254 BYTE buffer[128]; 1255 IMoniker * moniker_proxy; 1256 LPOLESTR display_name; 1257 IBindCtx *bindctx; 1258 1259 hr = IMoniker_IsDirty(moniker); 1260 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr); 1261 1262 /* Display Name */ 1263 1264 hr = CreateBindCtx(0, &bindctx); 1265 ok_ole_success(hr, CreateBindCtx); 1266 1267 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name); 1268 ok_ole_success(hr, IMoniker_GetDisplayName); 1269 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname); 1270 1271 CoTaskMemFree(display_name); 1272 IBindCtx_Release(bindctx); 1273 1274 hr = IMoniker_IsDirty(moniker); 1275 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr); 1276 1277 /* IROTData::GetComparisonData test */ 1278 1279 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata); 1280 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData); 1281 1282 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size); 1283 ok_ole_success(hr, IROTData_GetComparisonData); 1284 1285 if (hr != S_OK) moniker_size = 0; 1286 1287 /* first check we have the right amount of data */ 1288 ok(moniker_size == sizeof_expected_moniker_comparison_data, 1289 "%s: Size of comparison data differs (expected %d, actual %d)\n", 1290 testname, sizeof_expected_moniker_comparison_data, moniker_size); 1291 1292 /* then do a byte-by-byte comparison */ 1293 same = TRUE; 1294 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++) 1295 { 1296 if (expected_moniker_comparison_data[i] != buffer[i]) 1297 { 1298 same = FALSE; 1299 break; 1300 } 1301 } 1302 1303 ok(same, "%s: Comparison data differs\n", testname); 1304 if (!same) 1305 { 1306 for (i = 0; i < moniker_size; i++) 1307 { 1308 if (i % 8 == 0) printf(" "); 1309 printf("0x%02x,", buffer[i]); 1310 if (i % 8 == 7) printf("\n"); 1311 } 1312 printf("\n"); 1313 } 1314 1315 IROTData_Release(rotdata); 1316 1317 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1318 ok_ole_success(hr, CreateStreamOnHGlobal); 1319 1320 /* Saving */ 1321 1322 hr = IMoniker_Save(moniker, stream, TRUE); 1323 ok_ole_success(hr, IMoniker_Save); 1324 1325 hr = GetHGlobalFromStream(stream, &hglobal); 1326 ok_ole_success(hr, GetHGlobalFromStream); 1327 1328 moniker_size = GlobalSize(hglobal); 1329 1330 moniker_data = GlobalLock(hglobal); 1331 1332 /* first check we have the right amount of data */ 1333 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data), 1334 "%s: Size of saved data differs (expected %d, actual %d)\n", 1335 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size); 1336 1337 /* then do a byte-by-byte comparison */ 1338 same = TRUE; 1339 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++) 1340 { 1341 if (expected_moniker_saved_data[i] != moniker_data[i]) 1342 { 1343 same = FALSE; 1344 break; 1345 } 1346 } 1347 1348 ok(same, "%s: Saved data differs\n", testname); 1349 if (!same) 1350 { 1351 for (i = 0; i < moniker_size; i++) 1352 { 1353 if (i % 8 == 0) printf(" "); 1354 printf("0x%02x,", moniker_data[i]); 1355 if (i % 8 == 7) printf("\n"); 1356 } 1357 printf("\n"); 1358 } 1359 1360 GlobalUnlock(hglobal); 1361 1362 IStream_Release(stream); 1363 1364 /* Marshaling tests */ 1365 1366 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1367 ok_ole_success(hr, CreateStreamOnHGlobal); 1368 1369 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1370 ok_ole_success(hr, CoMarshalInterface); 1371 1372 hr = GetHGlobalFromStream(stream, &hglobal); 1373 ok_ole_success(hr, GetHGlobalFromStream); 1374 1375 moniker_size = GlobalSize(hglobal); 1376 1377 moniker_data = GlobalLock(hglobal); 1378 1379 /* first check we have the right amount of data */ 1380 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data), 1381 "%s: Size of marshaled data differs (expected %d, actual %d)\n", 1382 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size); 1383 1384 /* then do a byte-by-byte comparison */ 1385 same = TRUE; 1386 if (expected_moniker_marshal_data) 1387 { 1388 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++) 1389 { 1390 if (expected_moniker_marshal_data[i] != moniker_data[i]) 1391 { 1392 same = FALSE; 1393 break; 1394 } 1395 } 1396 } 1397 1398 ok(same, "%s: Marshaled data differs\n", testname); 1399 if (!same) 1400 { 1401 for (i = 0; i < moniker_size; i++) 1402 { 1403 if (i % 8 == 0) printf(" "); 1404 printf("0x%02x,", moniker_data[i]); 1405 if (i % 8 == 7) printf("\n"); 1406 } 1407 printf("\n"); 1408 } 1409 1410 GlobalUnlock(hglobal); 1411 1412 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL); 1413 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy); 1414 ok_ole_success(hr, CoUnmarshalInterface); 1415 1416 IStream_Release(stream); 1417 IMoniker_Release(moniker_proxy); 1418 } 1419 1420 static void test_class_moniker(void) 1421 { 1422 HRESULT hr; 1423 IMoniker *moniker; 1424 DWORD moniker_type; 1425 DWORD hash; 1426 IBindCtx *bindctx; 1427 IMoniker *inverse; 1428 IUnknown *unknown; 1429 FILETIME filetime; 1430 1431 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker); 1432 ok_ole_success(hr, CreateClassMoniker); 1433 if (!moniker) return; 1434 1435 test_moniker("class moniker", moniker, 1436 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data), 1437 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data), 1438 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data), 1439 expected_class_moniker_display_name); 1440 1441 /* Hashing */ 1442 1443 hr = IMoniker_Hash(moniker, &hash); 1444 ok_ole_success(hr, IMoniker_Hash); 1445 1446 ok(hash == CLSID_StdComponentCategoriesMgr.Data1, 1447 "Hash value != Data1 field of clsid, instead was 0x%08x\n", 1448 hash); 1449 1450 /* IsSystemMoniker test */ 1451 1452 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); 1453 ok_ole_success(hr, IMoniker_IsSystemMoniker); 1454 1455 ok(moniker_type == MKSYS_CLASSMONIKER, 1456 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n", 1457 moniker_type); 1458 1459 hr = CreateBindCtx(0, &bindctx); 1460 ok_ole_success(hr, CreateBindCtx); 1461 1462 /* IsRunning test */ 1463 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL); 1464 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr); 1465 1466 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL); 1467 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr); 1468 1469 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime); 1470 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr); 1471 1472 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1473 ok_ole_success(hr, IMoniker_BindToObject); 1474 IUnknown_Release(unknown); 1475 1476 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1477 ok_ole_success(hr, IMoniker_BindToStorage); 1478 IUnknown_Release(unknown); 1479 1480 IBindCtx_Release(bindctx); 1481 1482 hr = IMoniker_Inverse(moniker, &inverse); 1483 ok_ole_success(hr, IMoniker_Inverse); 1484 IMoniker_Release(inverse); 1485 1486 IMoniker_Release(moniker); 1487 } 1488 1489 static void test_file_moniker(WCHAR* path) 1490 { 1491 IStream *stream; 1492 IMoniker *moniker1 = NULL, *moniker2 = NULL; 1493 HRESULT hr; 1494 1495 hr = CreateFileMoniker(path, &moniker1); 1496 ok_ole_success(hr, CreateFileMoniker); 1497 1498 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1499 ok_ole_success(hr, CreateStreamOnHGlobal); 1500 1501 /* Marshal */ 1502 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1503 ok_ole_success(hr, CoMarshalInterface); 1504 1505 /* Rewind */ 1506 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL); 1507 ok_ole_success(hr, IStream_Seek); 1508 1509 /* Unmarshal */ 1510 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2); 1511 ok_ole_success(hr, CoUnmarshalInterface); 1512 1513 hr = IMoniker_IsEqual(moniker1, moniker2); 1514 ok_ole_success(hr, IsEqual); 1515 1516 IStream_Release(stream); 1517 if (moniker1) 1518 IMoniker_Release(moniker1); 1519 if (moniker2) 1520 IMoniker_Release(moniker2); 1521 } 1522 1523 static void test_file_monikers(void) 1524 { 1525 static WCHAR wszFile[][30] = { 1526 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0}, 1527 {'\\', 'a','b','c','d','e','f','g','\\','h','i','j','k','l','\\','m','n','o','p','q','r','s','t','u','.','m','n','o',0}, 1528 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */ 1529 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0}, 1530 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932) 1531 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932) 1532 * U+0100 .. = Latin extended-A 1533 */ 1534 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0}, 1535 }; 1536 1537 int i; 1538 1539 trace("ACP is %u\n", GetACP()); 1540 1541 for (i = 0; i < COUNTOF(wszFile); ++i) 1542 { 1543 int j ; 1544 if (i == 2) 1545 { 1546 BOOL used; 1547 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used ); 1548 if (used) 1549 { 1550 skip("string 2 doesn't round trip in codepage %u\n", GetACP() ); 1551 continue; 1552 } 1553 } 1554 for (j = lstrlenW(wszFile[i]); j > 0; --j) 1555 { 1556 wszFile[i][j] = 0; 1557 test_file_moniker(wszFile[i]); 1558 } 1559 } 1560 } 1561 1562 static void test_item_moniker(void) 1563 { 1564 HRESULT hr; 1565 IMoniker *moniker; 1566 DWORD moniker_type; 1567 DWORD hash; 1568 IBindCtx *bindctx; 1569 IMoniker *inverse; 1570 IUnknown *unknown; 1571 static const WCHAR wszDelimiter[] = {'!',0}; 1572 static const WCHAR wszObjectName[] = {'T','e','s','t',0}; 1573 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 }; 1574 1575 hr = CreateItemMoniker(wszDelimiter, wszObjectName, &moniker); 1576 ok_ole_success(hr, CreateItemMoniker); 1577 1578 test_moniker("item moniker", moniker, 1579 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data), 1580 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data), 1581 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data), 1582 expected_display_name); 1583 1584 /* Hashing */ 1585 1586 hr = IMoniker_Hash(moniker, &hash); 1587 ok_ole_success(hr, IMoniker_Hash); 1588 1589 ok(hash == 0x73c, 1590 "Hash value != 0x73c, instead was 0x%08x\n", 1591 hash); 1592 1593 /* IsSystemMoniker test */ 1594 1595 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); 1596 ok_ole_success(hr, IMoniker_IsSystemMoniker); 1597 1598 ok(moniker_type == MKSYS_ITEMMONIKER, 1599 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n", 1600 moniker_type); 1601 1602 hr = CreateBindCtx(0, &bindctx); 1603 ok_ole_success(hr, CreateBindCtx); 1604 1605 /* IsRunning test */ 1606 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL); 1607 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr); 1608 1609 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL); 1610 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr); 1611 1612 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1613 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr); 1614 1615 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1616 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr); 1617 1618 IBindCtx_Release(bindctx); 1619 1620 hr = IMoniker_Inverse(moniker, &inverse); 1621 ok_ole_success(hr, IMoniker_Inverse); 1622 IMoniker_Release(inverse); 1623 1624 IMoniker_Release(moniker); 1625 } 1626 1627 static void test_anti_moniker(void) 1628 { 1629 HRESULT hr; 1630 IMoniker *moniker; 1631 DWORD moniker_type; 1632 DWORD hash; 1633 IBindCtx *bindctx; 1634 FILETIME filetime; 1635 IMoniker *inverse; 1636 IUnknown *unknown; 1637 static const WCHAR expected_display_name[] = { '\\','.','.',0 }; 1638 1639 hr = CreateAntiMoniker(&moniker); 1640 ok_ole_success(hr, CreateAntiMoniker); 1641 if (!moniker) return; 1642 1643 test_moniker("anti moniker", moniker, 1644 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data), 1645 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data), 1646 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data), 1647 expected_display_name); 1648 1649 /* Hashing */ 1650 hr = IMoniker_Hash(moniker, &hash); 1651 ok_ole_success(hr, IMoniker_Hash); 1652 ok(hash == 0x80000001, 1653 "Hash value != 0x80000001, instead was 0x%08x\n", 1654 hash); 1655 1656 /* IsSystemMoniker test */ 1657 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); 1658 ok_ole_success(hr, IMoniker_IsSystemMoniker); 1659 ok(moniker_type == MKSYS_ANTIMONIKER, 1660 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n", 1661 moniker_type); 1662 1663 hr = IMoniker_Inverse(moniker, &inverse); 1664 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr); 1665 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse); 1666 1667 hr = CreateBindCtx(0, &bindctx); 1668 ok_ole_success(hr, CreateBindCtx); 1669 1670 /* IsRunning test */ 1671 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL); 1672 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr); 1673 1674 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime); 1675 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr); 1676 1677 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1678 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr); 1679 1680 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1681 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr); 1682 1683 IBindCtx_Release(bindctx); 1684 1685 IMoniker_Release(moniker); 1686 } 1687 1688 static void test_generic_composite_moniker(void) 1689 { 1690 HRESULT hr; 1691 IMoniker *moniker; 1692 IMoniker *moniker1; 1693 IMoniker *moniker2; 1694 DWORD moniker_type; 1695 DWORD hash; 1696 IBindCtx *bindctx; 1697 FILETIME filetime; 1698 IMoniker *inverse; 1699 IUnknown *unknown; 1700 static const WCHAR wszDelimiter1[] = {'!',0}; 1701 static const WCHAR wszObjectName1[] = {'T','e','s','t',0}; 1702 static const WCHAR wszDelimiter2[] = {'#',0}; 1703 static const WCHAR wszObjectName2[] = {'W','i','n','e',0}; 1704 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 }; 1705 1706 hr = CreateItemMoniker(wszDelimiter1, wszObjectName1, &moniker1); 1707 ok_ole_success(hr, CreateItemMoniker); 1708 hr = CreateItemMoniker(wszDelimiter2, wszObjectName2, &moniker2); 1709 ok_ole_success(hr, CreateItemMoniker); 1710 hr = CreateGenericComposite(moniker1, moniker2, &moniker); 1711 ok_ole_success(hr, CreateGenericComposite); 1712 1713 test_moniker("generic composite moniker", moniker, 1714 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data), 1715 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data), 1716 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data), 1717 expected_display_name); 1718 1719 /* Hashing */ 1720 1721 hr = IMoniker_Hash(moniker, &hash); 1722 ok_ole_success(hr, IMoniker_Hash); 1723 1724 ok(hash == 0xd87, 1725 "Hash value != 0xd87, instead was 0x%08x\n", 1726 hash); 1727 1728 /* IsSystemMoniker test */ 1729 1730 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); 1731 ok_ole_success(hr, IMoniker_IsSystemMoniker); 1732 1733 ok(moniker_type == MKSYS_GENERICCOMPOSITE, 1734 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n", 1735 moniker_type); 1736 1737 hr = CreateBindCtx(0, &bindctx); 1738 ok_ole_success(hr, CreateBindCtx); 1739 1740 /* IsRunning test */ 1741 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL); 1742 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr); 1743 1744 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL); 1745 todo_wine 1746 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr); 1747 1748 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime); 1749 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr); 1750 1751 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1752 todo_wine 1753 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr); 1754 1755 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1756 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr); 1757 1758 IBindCtx_Release(bindctx); 1759 1760 hr = IMoniker_Inverse(moniker, &inverse); 1761 ok_ole_success(hr, IMoniker_Inverse); 1762 IMoniker_Release(inverse); 1763 1764 IMoniker_Release(moniker); 1765 } 1766 1767 static void test_pointer_moniker(void) 1768 { 1769 HRESULT hr; 1770 IMoniker *moniker; 1771 DWORD moniker_type; 1772 DWORD hash; 1773 IBindCtx *bindctx; 1774 FILETIME filetime; 1775 IMoniker *inverse; 1776 IUnknown *unknown; 1777 IStream *stream; 1778 IROTData *rotdata; 1779 LPOLESTR display_name; 1780 1781 cLocks = 0; 1782 1783 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL); 1784 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1785 1786 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker); 1787 ok_ole_success(hr, CreatePointerMoniker); 1788 if (!moniker) return; 1789 1790 ok_more_than_one_lock(); 1791 1792 /* Display Name */ 1793 1794 hr = CreateBindCtx(0, &bindctx); 1795 ok_ole_success(hr, CreateBindCtx); 1796 1797 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name); 1798 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr); 1799 1800 IBindCtx_Release(bindctx); 1801 1802 hr = IMoniker_IsDirty(moniker); 1803 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr); 1804 1805 /* IROTData::GetComparisonData test */ 1806 1807 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata); 1808 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr); 1809 1810 /* Saving */ 1811 1812 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1813 ok_ole_success(hr, CreateStreamOnHGlobal); 1814 1815 hr = IMoniker_Save(moniker, stream, TRUE); 1816 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr); 1817 1818 IStream_Release(stream); 1819 1820 /* Hashing */ 1821 hr = IMoniker_Hash(moniker, &hash); 1822 ok_ole_success(hr, IMoniker_Hash); 1823 ok(hash == PtrToUlong(&Test_ClassFactory), 1824 "Hash value should have been 0x%08x, instead of 0x%08x\n", 1825 PtrToUlong(&Test_ClassFactory), hash); 1826 1827 /* IsSystemMoniker test */ 1828 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); 1829 ok_ole_success(hr, IMoniker_IsSystemMoniker); 1830 ok(moniker_type == MKSYS_POINTERMONIKER, 1831 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n", 1832 moniker_type); 1833 1834 hr = IMoniker_Inverse(moniker, &inverse); 1835 ok_ole_success(hr, IMoniker_Inverse); 1836 IMoniker_Release(inverse); 1837 1838 hr = CreateBindCtx(0, &bindctx); 1839 ok_ole_success(hr, CreateBindCtx); 1840 1841 /* IsRunning test */ 1842 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL); 1843 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr); 1844 1845 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime); 1846 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr); 1847 1848 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1849 ok_ole_success(hr, IMoniker_BindToObject); 1850 IUnknown_Release(unknown); 1851 1852 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1853 ok_ole_success(hr, IMoniker_BindToStorage); 1854 IUnknown_Release(unknown); 1855 1856 IMoniker_Release(moniker); 1857 1858 ok_no_locks(); 1859 1860 hr = CreatePointerMoniker(NULL, &moniker); 1861 ok_ole_success(hr, CreatePointerMoniker); 1862 1863 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1864 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr); 1865 1866 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); 1867 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr); 1868 1869 IBindCtx_Release(bindctx); 1870 1871 IMoniker_Release(moniker); 1872 } 1873 1874 static void test_bind_context(void) 1875 { 1876 HRESULT hr; 1877 IBindCtx *pBindCtx; 1878 IEnumString *pEnumString; 1879 BIND_OPTS2 bind_opts; 1880 HeapUnknown *unknown; 1881 HeapUnknown *unknown2; 1882 IUnknown *param_obj; 1883 ULONG refs; 1884 static const WCHAR wszParamName[] = {'G','e','m','m','a',0}; 1885 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0}; 1886 1887 hr = CreateBindCtx(0, NULL); 1888 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1889 1890 hr = CreateBindCtx(0xdeadbeef, &pBindCtx); 1891 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1892 1893 hr = CreateBindCtx(0, &pBindCtx); 1894 ok_ole_success(hr, "CreateBindCtx"); 1895 1896 bind_opts.cbStruct = -1; 1897 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts); 1898 ok_ole_success(hr, "IBindCtx_GetBindOptions"); 1899 ok(bind_opts.cbStruct == sizeof(bind_opts) || 1900 bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */ 1901 "bind_opts.cbStruct was %d\n", bind_opts.cbStruct); 1902 1903 bind_opts.cbStruct = sizeof(BIND_OPTS); 1904 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts); 1905 ok_ole_success(hr, "IBindCtx_GetBindOptions"); 1906 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct); 1907 1908 bind_opts.cbStruct = sizeof(bind_opts); 1909 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts); 1910 ok_ole_success(hr, "IBindCtx_GetBindOptions"); 1911 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct); 1912 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags); 1913 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode); 1914 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline); 1915 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags); 1916 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER), 1917 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext); 1918 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale); 1919 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo); 1920 1921 bind_opts.cbStruct = -1; 1922 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts); 1923 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1924 1925 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL); 1926 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1927 1928 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown)); 1929 unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl; 1930 unknown->refs = 1; 1931 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, &unknown->IUnknown_iface); 1932 ok_ole_success(hr, "IBindCtx_RegisterObjectParam"); 1933 1934 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, ¶m_obj); 1935 ok_ole_success(hr, "IBindCtx_GetObjectParam"); 1936 IUnknown_Release(param_obj); 1937 1938 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, ¶m_obj); 1939 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr); 1940 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj); 1941 1942 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent); 1943 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr); 1944 1945 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString); 1946 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr); 1947 ok(!pEnumString, "pEnumString should be NULL\n"); 1948 1949 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL); 1950 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)"); 1951 1952 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL); 1953 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr); 1954 1955 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown)); 1956 unknown2->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl; 1957 unknown2->refs = 1; 1958 hr = IBindCtx_RegisterObjectBound(pBindCtx, &unknown2->IUnknown_iface); 1959 ok_ole_success(hr, "IBindCtx_RegisterObjectBound"); 1960 1961 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface); 1962 ok_ole_success(hr, "IBindCtx_RevokeObjectBound"); 1963 1964 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface); 1965 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr); 1966 1967 IBindCtx_Release(pBindCtx); 1968 1969 refs = IUnknown_Release(&unknown->IUnknown_iface); 1970 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs); 1971 1972 refs = IUnknown_Release(&unknown2->IUnknown_iface); 1973 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs); 1974 } 1975 1976 static void test_save_load_filemoniker(void) 1977 { 1978 IMoniker* pMk; 1979 IStream* pStm; 1980 HRESULT hr; 1981 ULARGE_INTEGER size; 1982 LARGE_INTEGER zero_pos, dead_pos, nulls_pos; 1983 DWORD some_val = 0xFEDCBA98; 1984 int i; 1985 1986 /* see FileMonikerImpl_Save docs */ 1987 zero_pos.QuadPart = 0; 1988 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD); 1989 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD); 1990 1991 /* create the stream we're going to write to */ 1992 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm); 1993 ok_ole_success(hr, "CreateStreamOnHGlobal"); 1994 1995 size.u.LowPart = 128; 1996 hr = IStream_SetSize(pStm, size); 1997 ok_ole_success(hr, "IStream_SetSize"); 1998 1999 /* create and save a moniker */ 2000 hr = CreateFileMoniker(wszFileName1, &pMk); 2001 ok_ole_success(hr, "CreateFileMoniker"); 2002 2003 hr = IMoniker_Save(pMk, pStm, TRUE); 2004 ok_ole_success(hr, "IMoniker_Save"); 2005 IMoniker_Release(pMk); 2006 2007 /* overwrite the constants with various values */ 2008 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL); 2009 ok_ole_success(hr, "IStream_Seek"); 2010 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL); 2011 ok_ole_success(hr, "IStream_Write"); 2012 2013 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL); 2014 ok_ole_success(hr, "IStream_Seek"); 2015 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL); 2016 ok_ole_success(hr, "IStream_Write"); 2017 2018 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL); 2019 ok_ole_success(hr, "IStream_Seek"); 2020 for(i = 0; i < 5; ++i){ 2021 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL); 2022 ok_ole_success(hr, "IStream_Write"); 2023 } 2024 2025 /* go back to the start of the stream */ 2026 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL); 2027 ok_ole_success(hr, "IStream_Seek"); 2028 2029 /* create a new moniker and load into it */ 2030 hr = CreateFileMoniker(wszFileName1, &pMk); 2031 ok_ole_success(hr, "CreateFileMoniker"); 2032 2033 hr = IMoniker_Load(pMk, pStm); 2034 ok_ole_success(hr, "IMoniker_Load"); 2035 2036 IMoniker_Release(pMk); 2037 IStream_Release(pStm); 2038 } 2039 2040 START_TEST(moniker) 2041 { 2042 if (!GetProcAddress(GetModuleHandleA("ole32.dll"), "CoRegisterSurrogateEx")) { 2043 win_skip("skipping test on win9x\n"); 2044 return; 2045 } 2046 2047 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 2048 2049 test_ROT(); 2050 test_ROT_multiple_entries(); 2051 test_MkParseDisplayName(); 2052 test_class_moniker(); 2053 test_file_monikers(); 2054 test_item_moniker(); 2055 test_anti_moniker(); 2056 test_generic_composite_moniker(); 2057 test_pointer_moniker(); 2058 test_save_load_filemoniker(); 2059 2060 /* FIXME: test moniker creation funcs and parsing other moniker formats */ 2061 2062 test_bind_context(); 2063 2064 CoUninitialize(); 2065 } 2066