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