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