1 /* 2 * ItemMonikers implementation 3 * 4 * Copyright 1999 Noomen Hamza 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 <assert.h> 22 #include <stdarg.h> 23 #include <string.h> 24 25 #define COBJMACROS 26 #define NONAMELESSUNION 27 28 #include "winerror.h" 29 #include "windef.h" 30 #include "winbase.h" 31 #include "winuser.h" 32 #include "winnls.h" 33 #include "wine/debug.h" 34 #include "ole2.h" 35 #include "moniker.h" 36 37 WINE_DEFAULT_DEBUG_CHANNEL(ole); 38 39 /* ItemMoniker data structure */ 40 typedef struct ItemMonikerImpl{ 41 IMoniker IMoniker_iface; /* VTable relative to the IMoniker interface.*/ 42 IROTData IROTData_iface; /* VTable relative to the IROTData interface.*/ 43 LONG ref; 44 LPOLESTR itemName; /* item name identified by this ItemMoniker */ 45 LPOLESTR itemDelimiter; /* Delimiter string */ 46 IUnknown *pMarshal; /* custom marshaler */ 47 } ItemMonikerImpl; 48 49 static inline ItemMonikerImpl *impl_from_IMoniker(IMoniker *iface) 50 { 51 return CONTAINING_RECORD(iface, ItemMonikerImpl, IMoniker_iface); 52 } 53 54 static inline ItemMonikerImpl *impl_from_IROTData(IROTData *iface) 55 { 56 return CONTAINING_RECORD(iface, ItemMonikerImpl, IROTData_iface); 57 } 58 59 static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* iface); 60 61 /******************************************************************************* 62 * ItemMoniker_QueryInterface 63 *******************************************************************************/ 64 static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) 65 { 66 ItemMonikerImpl *This = impl_from_IMoniker(iface); 67 68 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); 69 70 if (!ppvObject) 71 return E_INVALIDARG; 72 73 /* Compare the riid with the interface IDs implemented by this object.*/ 74 if (IsEqualIID(&IID_IUnknown, riid) || 75 IsEqualIID(&IID_IPersist, riid) || 76 IsEqualIID(&IID_IPersistStream, riid) || 77 IsEqualIID(&IID_IMoniker, riid)) 78 *ppvObject = iface; 79 else if (IsEqualIID(&IID_IROTData, riid)) 80 *ppvObject = &This->IROTData_iface; 81 else if (IsEqualIID(&IID_IMarshal, riid)) 82 { 83 HRESULT hr = S_OK; 84 if (!This->pMarshal) 85 hr = MonikerMarshal_Create(iface, &This->pMarshal); 86 if (hr != S_OK) 87 return hr; 88 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject); 89 } 90 else 91 { 92 *ppvObject = NULL; 93 return E_NOINTERFACE; 94 } 95 96 IMoniker_AddRef(iface); 97 return S_OK; 98 } 99 100 /****************************************************************************** 101 * ItemMoniker_AddRef 102 ******************************************************************************/ 103 static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface) 104 { 105 ItemMonikerImpl *This = impl_from_IMoniker(iface); 106 107 TRACE("(%p)\n",This); 108 109 return InterlockedIncrement(&This->ref); 110 } 111 112 /****************************************************************************** 113 * ItemMoniker_Release 114 ******************************************************************************/ 115 static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface) 116 { 117 ItemMonikerImpl *This = impl_from_IMoniker(iface); 118 ULONG ref; 119 120 TRACE("(%p)\n",This); 121 122 ref = InterlockedDecrement(&This->ref); 123 124 /* destroy the object if there are no more references to it */ 125 if (ref == 0) ItemMonikerImpl_Destroy(This); 126 127 return ref; 128 } 129 130 /****************************************************************************** 131 * ItemMoniker_GetClassID 132 ******************************************************************************/ 133 static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) 134 { 135 TRACE("(%p,%p)\n",iface,pClassID); 136 137 if (pClassID==NULL) 138 return E_POINTER; 139 140 *pClassID = CLSID_ItemMoniker; 141 142 return S_OK; 143 } 144 145 /****************************************************************************** 146 * ItemMoniker_IsDirty 147 ******************************************************************************/ 148 static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface) 149 { 150 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty 151 method in the OLE-provided moniker interfaces always return S_FALSE because 152 their internal state never changes. */ 153 154 TRACE("(%p)\n",iface); 155 156 return S_FALSE; 157 } 158 159 /****************************************************************************** 160 * ItemMoniker_Load 161 ******************************************************************************/ 162 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm) 163 { 164 ItemMonikerImpl *This = impl_from_IMoniker(iface); 165 HRESULT res; 166 DWORD delimiterLength,nameLength,lenW; 167 CHAR *itemNameA,*itemDelimiterA; 168 ULONG bread; 169 170 TRACE("\n"); 171 172 /* for more details about data read by this function see comments of ItemMonikerImpl_Save function */ 173 174 /* read item delimiter string length + 1 */ 175 res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread); 176 if (bread != sizeof(DWORD)) 177 return E_FAIL; 178 179 /* read item delimiter string */ 180 if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength))) 181 return E_OUTOFMEMORY; 182 res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread); 183 if (bread != delimiterLength) 184 { 185 HeapFree( GetProcessHeap(), 0, itemDelimiterA ); 186 return E_FAIL; 187 } 188 189 lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 ); 190 This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR)); 191 if (!This->itemDelimiter) 192 { 193 HeapFree( GetProcessHeap(), 0, itemDelimiterA ); 194 return E_OUTOFMEMORY; 195 } 196 MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW ); 197 HeapFree( GetProcessHeap(), 0, itemDelimiterA ); 198 199 /* read item name string length + 1*/ 200 res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread); 201 if (bread != sizeof(DWORD)) 202 return E_FAIL; 203 204 /* read item name string */ 205 if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength))) 206 return E_OUTOFMEMORY; 207 res=IStream_Read(pStm,itemNameA,nameLength,&bread); 208 if (bread != nameLength) 209 { 210 HeapFree( GetProcessHeap(), 0, itemNameA ); 211 return E_FAIL; 212 } 213 214 lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 ); 215 This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR)); 216 if (!This->itemName) 217 { 218 HeapFree( GetProcessHeap(), 0, itemNameA ); 219 return E_OUTOFMEMORY; 220 } 221 MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW ); 222 HeapFree( GetProcessHeap(), 0, itemNameA ); 223 224 return res; 225 } 226 227 /****************************************************************************** 228 * ItemMoniker_Save 229 ******************************************************************************/ 230 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty) 231 { 232 ItemMonikerImpl *This = impl_from_IMoniker(iface); 233 HRESULT res; 234 CHAR *itemNameA,*itemDelimiterA; 235 236 /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */ 237 /* 2) String (type A): item delimiter string ('\0' included) */ 238 /* 3) DWORD : size of item name string ('\0' included) */ 239 /* 4) String (type A): item name string ('\0' included) */ 240 241 DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL); 242 DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL); 243 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength); 244 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength); 245 WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL); 246 WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL); 247 248 TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE"); 249 250 res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL); 251 res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL); 252 res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL); 253 res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL); 254 255 HeapFree(GetProcessHeap(), 0, itemNameA); 256 HeapFree(GetProcessHeap(), 0, itemDelimiterA); 257 258 return res; 259 } 260 261 /****************************************************************************** 262 * ItemMoniker_GetSizeMax 263 ******************************************************************************/ 264 static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize) 265 { 266 ItemMonikerImpl *This = impl_from_IMoniker(iface); 267 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1; 268 DWORD nameLength=lstrlenW(This->itemName)+1; 269 270 TRACE("(%p,%p)\n",iface,pcbSize); 271 272 if (!pcbSize) 273 return E_POINTER; 274 275 /* for more details see ItemMonikerImpl_Save comments */ 276 277 pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */ 278 delimiterLength*4 + /* item delimiter string */ 279 sizeof(DWORD) + /* DWORD which contains item name length */ 280 nameLength*4 + /* item name string */ 281 18; /* strange, but true */ 282 pcbSize->u.HighPart=0; 283 284 return S_OK; 285 } 286 287 /****************************************************************************** 288 * ItemMoniker_BindToObject 289 ******************************************************************************/ 290 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface, 291 IBindCtx* pbc, 292 IMoniker* pmkToLeft, 293 REFIID riid, 294 VOID** ppvResult) 295 { 296 ItemMonikerImpl *This = impl_from_IMoniker(iface); 297 HRESULT res; 298 IID refid=IID_IOleItemContainer; 299 IOleItemContainer *poic=0; 300 301 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); 302 303 if(ppvResult ==NULL) 304 return E_POINTER; 305 306 if(pmkToLeft==NULL) 307 return E_INVALIDARG; 308 309 *ppvResult=0; 310 311 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic); 312 313 if (SUCCEEDED(res)){ 314 315 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult); 316 317 IOleItemContainer_Release(poic); 318 } 319 320 return res; 321 } 322 323 /****************************************************************************** 324 * ItemMoniker_BindToStorage 325 ******************************************************************************/ 326 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface, 327 IBindCtx* pbc, 328 IMoniker* pmkToLeft, 329 REFIID riid, 330 VOID** ppvResult) 331 { 332 ItemMonikerImpl *This = impl_from_IMoniker(iface); 333 HRESULT res; 334 IOleItemContainer *poic=0; 335 336 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); 337 338 *ppvResult=0; 339 340 if(pmkToLeft==NULL) 341 return E_INVALIDARG; 342 343 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic); 344 345 if (SUCCEEDED(res)){ 346 347 res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult); 348 349 IOleItemContainer_Release(poic); 350 } 351 352 return res; 353 } 354 355 /****************************************************************************** 356 * ItemMoniker_Reduce 357 ******************************************************************************/ 358 static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface, 359 IBindCtx* pbc, 360 DWORD dwReduceHowFar, 361 IMoniker** ppmkToLeft, 362 IMoniker** ppmkReduced) 363 { 364 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced); 365 366 if (ppmkReduced==NULL) 367 return E_POINTER; 368 369 ItemMonikerImpl_AddRef(iface); 370 371 *ppmkReduced=iface; 372 373 return MK_S_REDUCED_TO_SELF; 374 } 375 /****************************************************************************** 376 * ItemMoniker_ComposeWith 377 ******************************************************************************/ 378 static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface, 379 IMoniker* pmkRight, 380 BOOL fOnlyIfNotGeneric, 381 IMoniker** ppmkComposite) 382 { 383 HRESULT res=S_OK; 384 DWORD mkSys,mkSys2; 385 IEnumMoniker* penumMk=0; 386 IMoniker *pmostLeftMk=0; 387 IMoniker* tempMkComposite=0; 388 389 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite); 390 391 if ((ppmkComposite==NULL)||(pmkRight==NULL)) 392 return E_POINTER; 393 394 *ppmkComposite=0; 395 396 IMoniker_IsSystemMoniker(pmkRight,&mkSys); 397 398 /* If pmkRight is an anti-moniker, the returned moniker is NULL */ 399 if(mkSys==MKSYS_ANTIMONIKER) 400 return res; 401 402 else 403 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ 404 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ 405 406 if(mkSys==MKSYS_GENERICCOMPOSITE){ 407 408 res=IMoniker_Enum(pmkRight,TRUE,&penumMk); 409 410 if (FAILED(res)) 411 return res; 412 413 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL); 414 415 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2); 416 417 if(mkSys2==MKSYS_ANTIMONIKER){ 418 419 IMoniker_Release(pmostLeftMk); 420 421 tempMkComposite=iface; 422 IMoniker_AddRef(iface); 423 424 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){ 425 426 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite); 427 428 IMoniker_Release(tempMkComposite); 429 IMoniker_Release(pmostLeftMk); 430 431 tempMkComposite=*ppmkComposite; 432 IMoniker_AddRef(tempMkComposite); 433 } 434 return res; 435 } 436 else 437 return CreateGenericComposite(iface,pmkRight,ppmkComposite); 438 } 439 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic 440 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns 441 a NULL moniker and a return value of MK_E_NEEDGENERIC */ 442 else 443 if (!fOnlyIfNotGeneric) 444 return CreateGenericComposite(iface,pmkRight,ppmkComposite); 445 446 else 447 return MK_E_NEEDGENERIC; 448 } 449 450 /****************************************************************************** 451 * ItemMoniker_Enum 452 ******************************************************************************/ 453 static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) 454 { 455 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker); 456 457 if (ppenumMoniker == NULL) 458 return E_POINTER; 459 460 *ppenumMoniker = NULL; 461 462 return S_OK; 463 } 464 465 /****************************************************************************** 466 * ItemMoniker_IsEqual 467 ******************************************************************************/ 468 static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) 469 { 470 471 CLSID clsid; 472 LPOLESTR dispName1,dispName2; 473 IBindCtx* bind; 474 HRESULT res = S_FALSE; 475 476 TRACE("(%p,%p)\n",iface,pmkOtherMoniker); 477 478 if (!pmkOtherMoniker) return S_FALSE; 479 480 481 /* check if both are ItemMoniker */ 482 if(FAILED (IMoniker_GetClassID(pmkOtherMoniker,&clsid))) return S_FALSE; 483 if(!IsEqualCLSID(&clsid,&CLSID_ItemMoniker)) return S_FALSE; 484 485 /* check if both displaynames are the same */ 486 if(SUCCEEDED ((res = CreateBindCtx(0,&bind)))) { 487 if(SUCCEEDED (IMoniker_GetDisplayName(iface,bind,NULL,&dispName1))) { 488 if(SUCCEEDED (IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2))) { 489 if(wcscmp(dispName1,dispName2)==0) res = S_OK; 490 CoTaskMemFree(dispName2); 491 } 492 CoTaskMemFree(dispName1); 493 } 494 } 495 return res; 496 } 497 498 /****************************************************************************** 499 * ItemMoniker_Hash 500 ******************************************************************************/ 501 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) 502 { 503 ItemMonikerImpl *This = impl_from_IMoniker(iface); 504 DWORD h = 0; 505 int i,len; 506 int off = 0; 507 LPOLESTR val; 508 509 if (pdwHash==NULL) 510 return E_POINTER; 511 512 val = This->itemName; 513 len = lstrlenW(val); 514 515 for (i = len ; i > 0; i--) 516 h = (h * 3) ^ towupper(val[off++]); 517 518 *pdwHash=h; 519 520 return S_OK; 521 } 522 523 /****************************************************************************** 524 * ItemMoniker_IsRunning 525 ******************************************************************************/ 526 static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface, 527 IBindCtx* pbc, 528 IMoniker* pmkToLeft, 529 IMoniker* pmkNewlyRunning) 530 { 531 ItemMonikerImpl *This = impl_from_IMoniker(iface); 532 IRunningObjectTable* rot; 533 HRESULT res; 534 IOleItemContainer *poic=0; 535 536 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning); 537 538 /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */ 539 /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */ 540 if (pmkToLeft==NULL) 541 if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK)) 542 return S_OK; 543 else { 544 if (pbc==NULL) 545 return E_INVALIDARG; 546 547 res=IBindCtx_GetRunningObjectTable(pbc,&rot); 548 549 if (FAILED(res)) 550 return res; 551 552 res = IRunningObjectTable_IsRunning(rot,iface); 553 554 IRunningObjectTable_Release(rot); 555 } 556 else{ 557 558 /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */ 559 /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/ 560 /* passing the string contained within this moniker. */ 561 562 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic); 563 564 if (SUCCEEDED(res)){ 565 566 res=IOleItemContainer_IsRunning(poic,This->itemName); 567 568 IOleItemContainer_Release(poic); 569 } 570 } 571 572 return res; 573 } 574 575 /****************************************************************************** 576 * ItemMoniker_GetTimeOfLastChange 577 ******************************************************************************/ 578 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, 579 IBindCtx* pbc, 580 IMoniker* pmkToLeft, 581 FILETIME* pItemTime) 582 { 583 IRunningObjectTable* rot; 584 HRESULT res; 585 IMoniker *compositeMk; 586 587 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime); 588 589 if (pItemTime==NULL) 590 return E_INVALIDARG; 591 592 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */ 593 if (pmkToLeft==NULL) 594 595 return MK_E_NOTBINDABLE; 596 else { 597 598 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */ 599 /* the time of last change. If the object is not in the ROT, the method calls */ 600 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */ 601 602 res=CreateGenericComposite(pmkToLeft,iface,&compositeMk); 603 if (FAILED(res)) 604 return res; 605 606 res=IBindCtx_GetRunningObjectTable(pbc,&rot); 607 if (FAILED(res)) { 608 IMoniker_Release(compositeMk); 609 return res; 610 } 611 612 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK) 613 614 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime); 615 616 IMoniker_Release(compositeMk); 617 } 618 619 return res; 620 } 621 622 /****************************************************************************** 623 * ItemMoniker_Inverse 624 ******************************************************************************/ 625 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) 626 { 627 TRACE("(%p,%p)\n",iface,ppmk); 628 629 if (ppmk==NULL) 630 return E_POINTER; 631 632 return CreateAntiMoniker(ppmk); 633 } 634 635 /****************************************************************************** 636 * ItemMoniker_CommonPrefixWith 637 ******************************************************************************/ 638 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) 639 { 640 DWORD mkSys; 641 642 TRACE("(%p,%p)\n", pmkOther, ppmkPrefix); 643 644 IMoniker_IsSystemMoniker(pmkOther,&mkSys); 645 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */ 646 /* to this moniker and returns MK_S_US */ 647 648 if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){ 649 650 *ppmkPrefix=iface; 651 652 IMoniker_AddRef(iface); 653 654 return MK_S_US; 655 } 656 else 657 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */ 658 /* the case where the other moniker is a generic composite. */ 659 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix); 660 } 661 662 /****************************************************************************** 663 * ItemMoniker_RelativePathTo 664 ******************************************************************************/ 665 static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) 666 { 667 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath); 668 669 if (ppmkRelPath==NULL) 670 return E_POINTER; 671 672 *ppmkRelPath=0; 673 674 return MK_E_NOTBINDABLE; 675 } 676 677 /****************************************************************************** 678 * ItemMoniker_GetDisplayName 679 ******************************************************************************/ 680 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface, 681 IBindCtx* pbc, 682 IMoniker* pmkToLeft, 683 LPOLESTR *ppszDisplayName) 684 { 685 ItemMonikerImpl *This = impl_from_IMoniker(iface); 686 687 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName); 688 689 if (ppszDisplayName==NULL) 690 return E_POINTER; 691 692 if (pmkToLeft!=NULL){ 693 return E_INVALIDARG; 694 } 695 696 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1)); 697 698 if (*ppszDisplayName==NULL) 699 return E_OUTOFMEMORY; 700 701 lstrcpyW(*ppszDisplayName,This->itemDelimiter); 702 lstrcatW(*ppszDisplayName,This->itemName); 703 704 TRACE("-- %s\n", debugstr_w(*ppszDisplayName)); 705 706 return S_OK; 707 } 708 709 /****************************************************************************** 710 * ItemMoniker_ParseDisplayName 711 ******************************************************************************/ 712 static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface, 713 IBindCtx* pbc, 714 IMoniker* pmkToLeft, 715 LPOLESTR pszDisplayName, 716 ULONG* pchEaten, 717 IMoniker** ppmkOut) 718 { 719 ItemMonikerImpl *This = impl_from_IMoniker(iface); 720 IOleItemContainer* poic=0; 721 IParseDisplayName* ppdn=0; 722 LPOLESTR displayName; 723 HRESULT res; 724 725 TRACE("%s\n", debugstr_w(pszDisplayName)); 726 727 /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */ 728 if (pmkToLeft==NULL) 729 730 return MK_E_SYNTAX; 731 732 else{ 733 /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */ 734 /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */ 735 /* name to IParseDisplayName::ParseDisplayName */ 736 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic); 737 738 if (SUCCEEDED(res)){ 739 740 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn); 741 742 res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName); 743 744 res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut); 745 746 IOleItemContainer_Release(poic); 747 IParseDisplayName_Release(ppdn); 748 } 749 } 750 return res; 751 } 752 753 /****************************************************************************** 754 * ItemMoniker_IsSystemMoniker 755 ******************************************************************************/ 756 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) 757 { 758 TRACE("(%p,%p)\n",iface,pwdMksys); 759 760 if (!pwdMksys) 761 return E_POINTER; 762 763 (*pwdMksys)=MKSYS_ITEMMONIKER; 764 765 return S_OK; 766 } 767 768 /******************************************************************************* 769 * ItemMonikerIROTData_QueryInterface 770 *******************************************************************************/ 771 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid, 772 void **ppvObject) 773 { 774 775 ItemMonikerImpl *This = impl_from_IROTData(iface); 776 777 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject); 778 779 return ItemMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject); 780 } 781 782 /*********************************************************************** 783 * ItemMonikerIROTData_AddRef 784 */ 785 static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface) 786 { 787 ItemMonikerImpl *This = impl_from_IROTData(iface); 788 789 TRACE("(%p)\n",iface); 790 791 return ItemMonikerImpl_AddRef(&This->IMoniker_iface); 792 } 793 794 /*********************************************************************** 795 * ItemMonikerIROTData_Release 796 */ 797 static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface) 798 { 799 ItemMonikerImpl *This = impl_from_IROTData(iface); 800 801 TRACE("(%p)\n",iface); 802 803 return ItemMonikerImpl_Release(&This->IMoniker_iface); 804 } 805 806 /****************************************************************************** 807 * ItemMonikerIROTData_GetComparisonData 808 ******************************************************************************/ 809 static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface, 810 BYTE* pbData, 811 ULONG cbMax, 812 ULONG* pcbData) 813 { 814 ItemMonikerImpl *This = impl_from_IROTData(iface); 815 int len = (lstrlenW(This->itemName)+1); 816 int i; 817 LPWSTR pszItemName; 818 LPWSTR pszItemDelimiter; 819 820 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData); 821 822 *pcbData = sizeof(CLSID) + sizeof(WCHAR) + len * sizeof(WCHAR); 823 if (cbMax < *pcbData) 824 return E_OUTOFMEMORY; 825 826 /* write CLSID */ 827 memcpy(pbData, &CLSID_ItemMoniker, sizeof(CLSID)); 828 /* write delimiter */ 829 pszItemDelimiter = (LPWSTR)(pbData+sizeof(CLSID)); 830 *pszItemDelimiter = *This->itemDelimiter; 831 /* write name */ 832 pszItemName = pszItemDelimiter + 1; 833 for (i = 0; i < len; i++) 834 pszItemName[i] = towupper(This->itemName[i]); 835 836 return S_OK; 837 } 838 839 /********************************************************************************/ 840 /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/ 841 /* IPersistStream and IMoniker functions. */ 842 static const IMonikerVtbl VT_ItemMonikerImpl = 843 { 844 ItemMonikerImpl_QueryInterface, 845 ItemMonikerImpl_AddRef, 846 ItemMonikerImpl_Release, 847 ItemMonikerImpl_GetClassID, 848 ItemMonikerImpl_IsDirty, 849 ItemMonikerImpl_Load, 850 ItemMonikerImpl_Save, 851 ItemMonikerImpl_GetSizeMax, 852 ItemMonikerImpl_BindToObject, 853 ItemMonikerImpl_BindToStorage, 854 ItemMonikerImpl_Reduce, 855 ItemMonikerImpl_ComposeWith, 856 ItemMonikerImpl_Enum, 857 ItemMonikerImpl_IsEqual, 858 ItemMonikerImpl_Hash, 859 ItemMonikerImpl_IsRunning, 860 ItemMonikerImpl_GetTimeOfLastChange, 861 ItemMonikerImpl_Inverse, 862 ItemMonikerImpl_CommonPrefixWith, 863 ItemMonikerImpl_RelativePathTo, 864 ItemMonikerImpl_GetDisplayName, 865 ItemMonikerImpl_ParseDisplayName, 866 ItemMonikerImpl_IsSystemMoniker 867 }; 868 869 /********************************************************************************/ 870 /* Virtual function table for the IROTData class. */ 871 static const IROTDataVtbl VT_ROTDataImpl = 872 { 873 ItemMonikerROTDataImpl_QueryInterface, 874 ItemMonikerROTDataImpl_AddRef, 875 ItemMonikerROTDataImpl_Release, 876 ItemMonikerROTDataImpl_GetComparisonData 877 }; 878 879 /****************************************************************************** 880 * ItemMoniker_Construct (local function) 881 *******************************************************************************/ 882 static HRESULT ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem) 883 { 884 885 int sizeStr1=lstrlenW(lpszItem), sizeStr2; 886 static const OLECHAR emptystr[1]; 887 LPCOLESTR delim; 888 889 TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem)); 890 891 /* Initialize the virtual function table. */ 892 This->IMoniker_iface.lpVtbl = &VT_ItemMonikerImpl; 893 This->IROTData_iface.lpVtbl = &VT_ROTDataImpl; 894 This->ref = 0; 895 This->pMarshal = NULL; 896 897 This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1)); 898 if (!This->itemName) 899 return E_OUTOFMEMORY; 900 lstrcpyW(This->itemName,lpszItem); 901 902 if (!lpszDelim) 903 FIXME("lpszDelim is NULL. Using empty string which is possibly wrong.\n"); 904 905 delim = lpszDelim ? lpszDelim : emptystr; 906 907 sizeStr2=lstrlenW(delim); 908 This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1)); 909 if (!This->itemDelimiter) { 910 HeapFree(GetProcessHeap(),0,This->itemName); 911 return E_OUTOFMEMORY; 912 } 913 lstrcpyW(This->itemDelimiter,delim); 914 return S_OK; 915 } 916 917 /****************************************************************************** 918 * ItemMoniker_Destroy (local function) 919 *******************************************************************************/ 920 static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* This) 921 { 922 TRACE("(%p)\n",This); 923 924 if (This->pMarshal) IUnknown_Release(This->pMarshal); 925 HeapFree(GetProcessHeap(),0,This->itemName); 926 HeapFree(GetProcessHeap(),0,This->itemDelimiter); 927 HeapFree(GetProcessHeap(),0,This); 928 929 return S_OK; 930 } 931 932 /****************************************************************************** 933 * CreateItemMoniker [OLE32.@] 934 ******************************************************************************/ 935 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim, LPCOLESTR lpszItem, IMoniker **ppmk) 936 { 937 ItemMonikerImpl* newItemMoniker; 938 HRESULT hr; 939 940 TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk); 941 942 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl)); 943 944 if (!newItemMoniker) 945 return STG_E_INSUFFICIENTMEMORY; 946 947 hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem); 948 949 if (FAILED(hr)){ 950 HeapFree(GetProcessHeap(),0,newItemMoniker); 951 return hr; 952 } 953 954 return ItemMonikerImpl_QueryInterface(&newItemMoniker->IMoniker_iface,&IID_IMoniker, 955 (void**)ppmk); 956 } 957 958 HRESULT WINAPI ItemMoniker_CreateInstance(IClassFactory *iface, 959 IUnknown *pUnk, REFIID riid, void **ppv) 960 { 961 ItemMonikerImpl* newItemMoniker; 962 HRESULT hr; 963 static const WCHAR wszEmpty[] = { 0 }; 964 965 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv); 966 967 *ppv = NULL; 968 969 if (pUnk) 970 return CLASS_E_NOAGGREGATION; 971 972 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl)); 973 if (!newItemMoniker) 974 return E_OUTOFMEMORY; 975 976 hr = ItemMonikerImpl_Construct(newItemMoniker, wszEmpty, wszEmpty); 977 978 if (SUCCEEDED(hr)) 979 hr = ItemMonikerImpl_QueryInterface(&newItemMoniker->IMoniker_iface, riid, ppv); 980 if (FAILED(hr)) 981 HeapFree(GetProcessHeap(),0,newItemMoniker); 982 983 return hr; 984 } 985