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