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