Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbeyj@wpi.edu>
[wine.git] / ole / itemmoniker.c
blob98fb5ab741b6c27b31377a7baeecb9d43c61c723
1 /***************************************************************************************
2 * ItemMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
7 #include <assert.h>
8 #include "winerror.h"
9 #include "debug.h"
10 #include "heap.h"
11 #include "winuser.h"
12 #include "file.h"
13 #include "winreg.h"
14 #include "objbase.h"
15 #include "wine/obj_inplace.h"
17 DEFAULT_DEBUG_CHANNEL(ole)
19 /* ItemMoniker data structure */
20 typedef struct ItemMonikerImpl{
22 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
24 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
25 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
27 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
29 ULONG ref; /* reference counter for this object */
31 LPOLESTR itemName; /* item name identified by this ItemMoniker */
33 LPOLESTR itemDelimiter; /* Delimiter string */
35 } ItemMonikerImpl;
37 /********************************************************************************/
38 /* ItemMoniker prototype functions : */
40 /* IUnknown prototype functions */
41 static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
42 static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface);
43 static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface);
45 /* IPersist prototype functions */
46 static HRESULT WINAPI ItemMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID);
48 /* IPersistStream prototype functions */
49 static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface);
50 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface, IStream* pStm);
51 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
52 static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
54 /* IMoniker prototype functions */
55 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
56 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
57 static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
58 static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
59 static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
60 static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
61 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
62 static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
63 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime);
64 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
65 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
66 static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
67 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
68 static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
69 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
71 /* Local function used by ItemMoniker implementation */
72 HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszPathName);
73 HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
75 /********************************************************************************/
76 /* IROTData prototype functions */
78 /* IUnknown prototype functions */
79 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
80 static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface);
81 static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface);
83 /* IROTData prototype function */
84 static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
86 /********************************************************************************/
87 /* Virtual function table for the ItemMonikerImpl class witch include Ipersist,*/
88 /* IPersistStream and IMoniker functions. */
89 static ICOM_VTABLE(IMoniker) VT_ItemMonikerImpl =
91 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
92 ItemMonikerImpl_QueryInterface,
93 ItemMonikerImpl_AddRef,
94 ItemMonikerImpl_Release,
95 ItemMonikerImpl_GetClassID,
96 ItemMonikerImpl_IsDirty,
97 ItemMonikerImpl_Load,
98 ItemMonikerImpl_Save,
99 ItemMonikerImpl_GetSizeMax,
100 ItemMonikerImpl_BindToObject,
101 ItemMonikerImpl_BindToStorage,
102 ItemMonikerImpl_Reduce,
103 ItemMonikerImpl_ComposeWith,
104 ItemMonikerImpl_Enum,
105 ItemMonikerImpl_IsEqual,
106 ItemMonikerImpl_Hash,
107 ItemMonikerImpl_IsRunning,
108 ItemMonikerImpl_GetTimeOfLastChange,
109 ItemMonikerImpl_Inverse,
110 ItemMonikerImpl_CommonPrefixWith,
111 ItemMonikerImpl_RelativePathTo,
112 ItemMonikerImpl_GetDisplayName,
113 ItemMonikerImpl_ParseDisplayName,
114 ItemMonikerImpl_IsSystemMoniker
117 /********************************************************************************/
118 /* Virtual function table for the IROTData class. */
119 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
121 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
122 ItemMonikerROTDataImpl_QueryInterface,
123 ItemMonikerROTDataImpl_AddRef,
124 ItemMonikerROTDataImpl_Release,
125 ItemMonikerROTDataImpl_GetComparaisonData
128 /*******************************************************************************
129 * ItemMoniker_QueryInterface
130 *******************************************************************************/
131 HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
133 ICOM_THIS(ItemMonikerImpl,iface);
135 TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
137 /* Perform a sanity check on the parameters.*/
138 if ( (This==0) || (ppvObject==0) )
139 return E_INVALIDARG;
141 /* Initialize the return parameter */
142 *ppvObject = 0;
144 /* Compare the riid with the interface IDs implemented by this object.*/
145 if (IsEqualIID(&IID_IUnknown, riid) ||
146 IsEqualIID(&IID_IPersist, riid) ||
147 IsEqualIID(&IID_IPersistStream, riid) ||
148 IsEqualIID(&IID_IMoniker, riid)
150 *ppvObject = iface;
152 else if (IsEqualIID(&IID_IROTData, riid))
153 *ppvObject = (IROTData*)&(This->lpvtbl2);
155 /* Check that we obtained an interface.*/
156 if ((*ppvObject)==0)
157 return E_NOINTERFACE;
159 /* Query Interface always increases the reference count by one when it is successful */
160 ItemMonikerImpl_AddRef(iface);
162 return S_OK;
165 /******************************************************************************
166 * ItemMoniker_AddRef
167 ******************************************************************************/
168 ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
170 ICOM_THIS(ItemMonikerImpl,iface);
172 TRACE(ole,"(%p)\n",This);
174 return ++(This->ref);
177 /******************************************************************************
178 * ItemMoniker_Release
179 ******************************************************************************/
180 ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
182 ICOM_THIS(ItemMonikerImpl,iface);
184 TRACE(ole,"(%p)\n",This);
186 This->ref--;
188 /* destroy the object if there's no more reference on it */
189 if (This->ref==0){
191 ItemMonikerImpl_Destroy(This);
193 return 0;
195 return This->ref;;
198 /******************************************************************************
199 * ItemMoniker_GetClassID
200 ******************************************************************************/
201 HRESULT WINAPI ItemMonikerImpl_GetClassID(const IMoniker* iface,CLSID *pClassID)
203 TRACE(ole,"(%p,%p),stub!\n",iface,pClassID);
205 if (pClassID==NULL)
206 return E_POINTER;
208 *pClassID = CLSID_ItemMoniker;
210 return S_OK;
213 /******************************************************************************
214 * ItemMoniker_IsDirty
215 ******************************************************************************/
216 HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
218 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
219 method in the OLE-provided moniker interfaces always return S_FALSE because
220 their internal state never changes. */
222 TRACE(ole,"(%p)\n",iface);
224 return S_FALSE;
227 /******************************************************************************
228 * ItemMoniker_Load
229 ******************************************************************************/
230 HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
233 ICOM_THIS(ItemMonikerImpl,iface);
234 HRESULT res;
235 DWORD delimiterLength,nameLength;
236 CHAR *itemNameA,*itemDelimiterA;
237 ULONG bread;
239 /* for more details about data read by this function see coments of ItemMonikerImpl_Save function */
241 /* read item delimiter string length + 1 */
242 res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);
243 if (bread != sizeof(DWORD))
244 return E_FAIL;
246 /* read item delimiter string */
247 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
248 res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
249 if (bread != delimiterLength)
250 return E_FAIL;
252 This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,delimiterLength*sizeof(WCHAR));
253 if (!This->itemDelimiter)
254 return E_OUTOFMEMORY;
256 lstrcpyAtoW(This->itemDelimiter,itemDelimiterA);
258 /* read item name string length + 1*/
259 res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
260 if (bread != sizeof(DWORD))
261 return E_FAIL;
263 /* read item name string */
264 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
265 res=IStream_Read(pStm,itemNameA,nameLength,&bread);
266 if (bread != nameLength)
267 return E_FAIL;
269 This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,nameLength*sizeof(WCHAR));
270 if (!This->itemName)
271 return E_OUTOFMEMORY;
273 lstrcpyAtoW(This->itemName,itemNameA);
275 return res;
278 /******************************************************************************
279 * ItemMoniker_Save
280 ******************************************************************************/
281 HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,
282 IStream* pStm,/* pointer to the stream where the object is to be saved */
283 BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
285 ICOM_THIS(ItemMonikerImpl,iface);
286 HRESULT res;
287 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
288 DWORD nameLength=lstrlenW(This->itemName)+1;
289 CHAR *itemNameA,*itemDelimiterA;
291 /* data writen by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
292 /* 2) String (type A): item delimiter string ('\0' included) */
293 /* 3) DWORD : size of item name string ('\0' included) */
294 /* 4) String (type A): item name string ('\0' included) */
296 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
297 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
298 lstrcpyWtoA(itemNameA,This->itemName);
299 lstrcpyWtoA(itemDelimiterA,This->itemDelimiter);
301 res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
302 res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
303 res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
304 res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);
306 return res;
309 /******************************************************************************
310 * ItemMoniker_GetSizeMax
311 ******************************************************************************/
312 HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,
313 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
315 ICOM_THIS(ItemMonikerImpl,iface);
316 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
317 DWORD nameLength=lstrlenW(This->itemName)+1;
319 TRACE(ole,"(%p,%p)\n",iface,pcbSize);
321 if (pcbSize!=NULL)
322 return E_POINTER;
324 /* for more details see ItemMonikerImpl_Save coments */
326 pcbSize->LowPart = sizeof(DWORD) + /* DWORD witch contains delimiter length */
327 delimiterLength + /* item delimiter string */
328 sizeof(DWORD) + /* DWORD witch contains item name length */
329 nameLength + /* item name string */
330 34; /* this constant was added ! because when I tested this function it usually */
331 /* returns 34 bytes more than the number of bytes used by IMoniker::Save function */
332 pcbSize->HighPart=0;
334 return S_OK;
337 /******************************************************************************
338 * ItemMoniker_Construct (local function)
339 *******************************************************************************/
340 HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
343 int sizeStr1=lstrlenW(lpszItem);
344 int sizeStr2=lstrlenW(lpszDelim);
346 TRACE(ole,"(%p,%p)\n",This,lpszItem);
348 /* Initialize the virtual fgunction table. */
349 This->lpvtbl1 = &VT_ItemMonikerImpl;
350 This->lpvtbl2 = &VT_ROTDataImpl;
351 This->ref = 0;
353 This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
354 This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
356 if ((This->itemName==NULL)||(This->itemDelimiter==NULL))
357 return E_OUTOFMEMORY;
359 lstrcpyW(This->itemName,lpszItem);
360 lstrcpyW(This->itemDelimiter,lpszDelim);
362 return S_OK;
365 /******************************************************************************
366 * ItemMoniker_Destroy (local function)
367 *******************************************************************************/
368 HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
370 TRACE(ole,"(%p)\n",This);
372 if (This->itemName)
373 HeapFree(GetProcessHeap(),0,This->itemName);
375 if (This->itemDelimiter)
376 HeapFree(GetProcessHeap(),0,This->itemDelimiter);
378 HeapFree(GetProcessHeap(),0,This);
380 return S_OK;
383 /******************************************************************************
384 * ItemMoniker_BindToObject
385 ******************************************************************************/
386 HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
387 IBindCtx* pbc,
388 IMoniker* pmkToLeft,
389 REFIID riid,
390 VOID** ppvResult)
392 ICOM_THIS(ItemMonikerImpl,iface);
394 HRESULT res;
395 IID refid=IID_IOleItemContainer;
396 IOleItemContainer *poic=0;
398 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
400 if(ppvResult ==NULL)
401 return E_POINTER;
403 if(pmkToLeft==NULL)
404 return E_INVALIDARG;
406 *ppvResult=0;
408 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
410 if (SUCCEEDED(res)){
412 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);
414 IOleItemContainer_Release(poic);
417 return res;
420 /******************************************************************************
421 * ItemMoniker_BindToStorage
422 ******************************************************************************/
423 HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
424 IBindCtx* pbc,
425 IMoniker* pmkToLeft,
426 REFIID riid,
427 VOID** ppvResult)
429 ICOM_THIS(ItemMonikerImpl,iface);
431 HRESULT res;
432 IOleItemContainer *poic=0;
434 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
436 *ppvResult=0;
438 if(pmkToLeft==NULL)
439 return E_INVALIDARG;
441 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
443 if (SUCCEEDED(res)){
445 res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);
447 IOleItemContainer_Release(poic);
450 return res;
453 /******************************************************************************
454 * ItemMoniker_Reduce
455 ******************************************************************************/
456 HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
457 IBindCtx* pbc,
458 DWORD dwReduceHowFar,
459 IMoniker** ppmkToLeft,
460 IMoniker** ppmkReduced)
462 TRACE(ole,"(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
464 if (ppmkReduced==NULL)
465 return E_POINTER;
467 ItemMonikerImpl_AddRef(iface);
469 *ppmkReduced=iface;
471 return MK_S_REDUCED_TO_SELF;
473 /******************************************************************************
474 * ItemMoniker_ComposeWith
475 ******************************************************************************/
476 HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
477 IMoniker* pmkRight,
478 BOOL fOnlyIfNotGeneric,
479 IMoniker** ppmkComposite)
481 HRESULT res=S_OK;
482 DWORD mkSys,mkSys2;
483 IEnumMoniker* penumMk=0;
484 IMoniker *pmostLeftMk=0;
485 IMoniker* tempMkComposite=0;
487 TRACE(ole,"(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
489 if ((ppmkComposite==NULL)||(pmkRight==NULL))
490 return E_POINTER;
492 *ppmkComposite=0;
494 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
496 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
497 if(mkSys==MKSYS_ANTIMONIKER)
498 return res;
500 else
501 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
502 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
504 if(mkSys==MKSYS_GENERICCOMPOSITE){
506 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
508 if (FAILED(res))
509 return res;
511 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
513 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
515 if(mkSys2==MKSYS_ANTIMONIKER){
517 IMoniker_Release(pmostLeftMk);
519 tempMkComposite=iface;
520 IMoniker_AddRef(iface);
522 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
524 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
526 IMoniker_Release(tempMkComposite);
527 IMoniker_Release(pmostLeftMk);
529 tempMkComposite=*ppmkComposite;
530 IMoniker_AddRef(tempMkComposite);
532 return res;
534 else
535 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
537 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
538 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
539 a NULL moniker and a return value of MK_E_NEEDGENERIC */
540 else
541 if (!fOnlyIfNotGeneric)
542 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
544 else
545 return MK_E_NEEDGENERIC;
548 /******************************************************************************
549 * ItemMoniker_Enum
550 ******************************************************************************/
551 HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
553 TRACE(ole,"(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
555 if (ppenumMoniker == NULL)
556 return E_POINTER;
558 *ppenumMoniker = NULL;
560 return S_OK;
563 /******************************************************************************
564 * ItemMoniker_IsEqual
565 ******************************************************************************/
566 HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
569 CLSID clsid;
570 LPOLESTR dispName1,dispName2;
571 IBindCtx* bind;
572 HRESULT res;
574 TRACE(ole,"(%p,%p)\n",iface,pmkOtherMoniker);
576 if (pmkOtherMoniker==NULL)
577 return S_FALSE;
579 /* This method returns S_OK if both monikers are item monikers and their display names are */
580 /* identical (using a case-insensitive comparison); otherwise, the method returns S_FALSE. */
582 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
584 if (!IsEqualCLSID(&clsid,&CLSID_ItemMoniker))
585 return S_FALSE;
587 res=CreateBindCtx(0,&bind);
588 if (FAILED(res))
589 return res;
591 IMoniker_GetDisplayName(iface,bind,NULL,&dispName1);
592 IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2);
594 if (lstrcmpW(dispName1,dispName2)!=0)
595 return S_FALSE;
597 return S_OK;
600 /******************************************************************************
601 * ItemMoniker_Hash
602 ******************************************************************************/
603 HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
605 ICOM_THIS(ItemMonikerImpl,iface);
607 int h = 0,i,skip,len;
608 int off = 0;
609 LPOLESTR val;
611 if (pdwHash==NULL)
612 return E_POINTER;
614 val = This->itemName;
615 len = lstrlenW(val);
617 if (len < 16) {
618 for (i = len ; i > 0; i--) {
619 h = (h * 37) + val[off++];
621 } else {
622 /* only sample some characters */
623 skip = len / 8;
624 for (i = len ; i > 0; i -= skip, off += skip) {
625 h = (h * 39) + val[off];
629 *pdwHash=h;
631 return S_OK;
634 /******************************************************************************
635 * ItemMoniker_IsRunning
636 ******************************************************************************/
637 HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
638 IBindCtx* pbc,
639 IMoniker* pmkToLeft,
640 IMoniker* pmkNewlyRunning)
642 IRunningObjectTable* rot;
643 HRESULT res;
644 IOleItemContainer *poic=0;
645 ICOM_THIS(ItemMonikerImpl,iface);
647 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
649 /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
650 /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */
651 if (pmkToLeft==NULL)
652 if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
653 return S_OK;
654 else {
655 if (pbc==NULL)
656 return E_POINTER;
658 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
660 if (FAILED(res))
661 return res;
663 res = IRunningObjectTable_IsRunning(rot,iface);
665 IRunningObjectTable_Release(rot);
667 else{
669 /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */
670 /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
671 /* passing the string contained within this moniker. */
673 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
675 if (SUCCEEDED(res)){
677 res=IOleItemContainer_IsRunning(poic,This->itemName);
679 IOleItemContainer_Release(poic);
683 return res;
686 /******************************************************************************
687 * ItemMoniker_GetTimeOfLastChange
688 ******************************************************************************/
689 HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
690 IBindCtx* pbc,
691 IMoniker* pmkToLeft,
692 FILETIME* pItemTime)
694 IRunningObjectTable* rot;
695 HRESULT res;
696 IMoniker *compositeMk;
698 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
700 if (pItemTime==NULL)
701 return E_INVALIDARG;
703 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
704 if (pmkToLeft==NULL)
706 return MK_E_NOTBINDABLE;
707 else {
709 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
710 /* the time of last change. If the object is not in the ROT, the method calls */
711 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
713 res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
715 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
717 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
719 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
721 IMoniker_Release(compositeMk);
724 return res;
727 /******************************************************************************
728 * ItemMoniker_Inverse
729 ******************************************************************************/
730 HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
732 TRACE(ole,"(%p,%p)\n",iface,ppmk);
734 if (ppmk==NULL)
735 return E_POINTER;
737 return CreateAntiMoniker(ppmk);
740 /******************************************************************************
741 * ItemMoniker_CommonPrefixWith
742 ******************************************************************************/
743 HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
745 DWORD mkSys;
746 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
747 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
748 /* to this moniker and returns MK_S_US */
750 if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
752 *ppmkPrefix=iface;
754 IMoniker_AddRef(iface);
756 return MK_S_US;
758 else
759 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
760 /* the case where the other moniker is a generic composite. */
761 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
764 /******************************************************************************
765 * ItemMoniker_RelativePathTo
766 ******************************************************************************/
767 HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
769 TRACE(ole,"(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
771 if (ppmkRelPath==NULL)
772 return E_POINTER;
774 *ppmkRelPath=0;
776 return MK_E_NOTBINDABLE;
779 /******************************************************************************
780 * ItemMoniker_GetDisplayName
781 ******************************************************************************/
782 HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
783 IBindCtx* pbc,
784 IMoniker* pmkToLeft,
785 LPOLESTR *ppszDisplayName)
787 ICOM_THIS(ItemMonikerImpl,iface);
789 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
791 if (ppszDisplayName==NULL)
792 return E_POINTER;
794 if (pmkToLeft!=NULL){
795 return E_INVALIDARG;
798 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));
800 if (*ppszDisplayName==NULL)
801 return E_OUTOFMEMORY;
803 lstrcpyW(*ppszDisplayName,This->itemDelimiter);
804 lstrcatW(*ppszDisplayName,This->itemName);
806 return S_OK;
809 /******************************************************************************
810 * ItemMoniker_ParseDisplayName
811 ******************************************************************************/
812 HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
813 IBindCtx* pbc,
814 IMoniker* pmkToLeft,
815 LPOLESTR pszDisplayName,
816 ULONG* pchEaten,
817 IMoniker** ppmkOut)
819 IOleItemContainer* poic=0;
820 IParseDisplayName* ppdn=0;
821 LPOLESTR displayName;
822 HRESULT res;
823 ICOM_THIS(ItemMonikerImpl,iface);
825 /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
826 if (pmkToLeft==NULL)
828 return MK_E_SYNTAX;
830 else{
831 /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
832 /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */ /* name to IParseDisplayName::ParseDisplayName */
833 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
835 if (SUCCEEDED(res)){
837 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
839 res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);
841 res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);
843 IOleItemContainer_Release(poic);
844 IParseDisplayName_Release(ppdn);
847 return res;
850 /******************************************************************************
851 * ItemMoniker_IsSystemMonker
852 ******************************************************************************/
853 HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
855 TRACE(ole,"(%p,%p)\n",iface,pwdMksys);
857 if (!pwdMksys)
858 return E_POINTER;
860 (*pwdMksys)=MKSYS_ITEMMONIKER;
862 return S_OK;
865 /*******************************************************************************
866 * ItemMonikerIROTData_QueryInterface
867 *******************************************************************************/
868 HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
871 ICOM_THIS_From_IROTData(IMoniker, iface);
873 TRACE(ole,"(%p,%p,%p)\n",iface,riid,ppvObject);
875 return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);
878 /***********************************************************************
879 * ItemMonikerIROTData_AddRef
881 ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
883 ICOM_THIS_From_IROTData(IMoniker, iface);
885 TRACE(ole,"(%p)\n",iface);
887 return ItemMonikerImpl_AddRef(This);
890 /***********************************************************************
891 * ItemMonikerIROTData_Release
893 ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
895 ICOM_THIS_From_IROTData(IMoniker, iface);
897 TRACE(ole,"(%p)\n",iface);
899 return ItemMonikerImpl_Release(This);
902 /******************************************************************************
903 * ItemMonikerIROTData_GetComparaisonData
904 ******************************************************************************/
905 HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
906 BYTE* pbData,
907 ULONG cbMax,
908 ULONG* pcbData)
910 FIXME(ole,"(),stub!\n");
911 return E_NOTIMPL;
914 /******************************************************************************
915 * CreateItemMoniker16 [OLE2.28]
916 ******************************************************************************/
917 HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim,LPCOLESTR lpszItem,LPMONIKER* ppmk)
920 FIXME(ole,"(%s,%p),stub!\n",lpszDelim,ppmk);
921 *ppmk = NULL;
922 return E_NOTIMPL;
925 /******************************************************************************
926 * CreateItemMoniker [OLE.55]
927 ******************************************************************************/
928 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk)
930 ItemMonikerImpl* newItemMoniker = 0;
931 HRESULT hr = S_OK;
932 IID riid=IID_IMoniker;
934 TRACE(ole,"(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk);
936 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
938 if (newItemMoniker == 0)
939 return STG_E_INSUFFICIENTMEMORY;
941 hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
943 if (FAILED(hr)){
945 HeapFree(GetProcessHeap(),0,newItemMoniker);
946 return hr;
949 return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk);