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