Fixed miscellaneous typos, syntactic and grammatical errors.
[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 "winnls.h"
11 #include "debugtools.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,lenW;
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     if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength)))
250         return E_OUTOFMEMORY;
251     res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
252     if (bread != delimiterLength)
253     {
254         HeapFree( GetProcessHeap(), 0, itemDelimiterA );
255         return E_FAIL;
256     }
257
258     lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 );
259     This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR));
260     if (!This->itemDelimiter)
261     {
262         HeapFree( GetProcessHeap(), 0, itemDelimiterA );
263         return E_OUTOFMEMORY;
264     }
265     MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW );
266     HeapFree( GetProcessHeap(), 0, itemDelimiterA );
267
268     /* read item name string length + 1*/
269     res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
270     if (bread != sizeof(DWORD))
271         return E_FAIL;
272
273     /* read item name string */
274     if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength)))
275         return E_OUTOFMEMORY;
276     res=IStream_Read(pStm,itemNameA,nameLength,&bread);
277     if (bread != nameLength)
278     {
279         HeapFree( GetProcessHeap(), 0, itemNameA );
280         return E_FAIL;
281     }
282
283     lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 );
284     This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR));
285     if (!This->itemName)
286     {
287         HeapFree( GetProcessHeap(), 0, itemNameA );
288         return E_OUTOFMEMORY;
289     }
290     MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW );
291     HeapFree( GetProcessHeap(), 0, itemNameA );
292
293     return res;
294 }
295
296 /******************************************************************************
297  *        ItemMoniker_Save
298  ******************************************************************************/
299 HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,
300                                     IStream* pStm,/* pointer to the stream where the object is to be saved */
301                                     BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
302 {
303     ICOM_THIS(ItemMonikerImpl,iface);
304     HRESULT res;
305     CHAR *itemNameA,*itemDelimiterA;
306
307     /* data writen by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
308     /*                                    2) String (type A): item delimiter string ('\0' included)          */
309     /*                                    3) DWORD : size of item name string ('\0' included)       */
310     /*                                    4) String (type A): item name string ('\0' included)               */
311
312     DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL);
313     DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL);
314     itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
315     itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
316     WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL);
317     WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL);
318
319     res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
320     res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
321     res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
322     res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);
323
324     return res;
325 }
326
327 /******************************************************************************
328  *        ItemMoniker_GetSizeMax
329  ******************************************************************************/
330 HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,
331                                           ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
332 {
333     ICOM_THIS(ItemMonikerImpl,iface);
334     DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
335     DWORD nameLength=lstrlenW(This->itemName)+1;
336
337     TRACE("(%p,%p)\n",iface,pcbSize);
338
339     if (pcbSize!=NULL)
340         return E_POINTER;
341
342     /* for more details see ItemMonikerImpl_Save coments */
343     
344     pcbSize->s.LowPart =  sizeof(DWORD) + /* DWORD witch contains delimiter length */
345                         delimiterLength + /* item delimiter string */
346                         sizeof(DWORD) + /* DWORD witch contains item name length */
347                         nameLength + /* item name string */
348                         34; /* this constant was added ! because when I tested this function it usually */
349                             /*  returns 34 bytes more than the number of bytes used by IMoniker::Save function */
350     pcbSize->s.HighPart=0;
351
352     return S_OK;
353 }
354
355 /******************************************************************************
356  *         ItemMoniker_Construct (local function)
357  *******************************************************************************/
358 HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
359 {
360
361     int sizeStr1=lstrlenW(lpszItem), sizeStr2;
362     static const OLECHAR emptystr[1];
363     LPCOLESTR   delim;
364
365     TRACE("(%p,%p)\n",This,lpszItem);
366
367     /* Initialize the virtual fgunction table. */
368     This->lpvtbl1      = &VT_ItemMonikerImpl;
369     This->lpvtbl2      = &VT_ROTDataImpl;
370     This->ref          = 0;
371
372     This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
373     if (!This->itemName)
374         return E_OUTOFMEMORY;
375     strcpyW(This->itemName,lpszItem);
376
377     if (!lpszDelim)
378         FIXME("lpszDelim is NULL. Using empty string which is possibly wrong.\n");
379
380     delim = lpszDelim ? lpszDelim : emptystr;
381
382     sizeStr2=strlenW(delim);
383     This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
384     if (!This->itemDelimiter) {
385         HeapFree(GetProcessHeap(),0,This->itemName);
386         return E_OUTOFMEMORY;
387     }
388     strcpyW(This->itemDelimiter,delim);
389     return S_OK;
390 }
391
392 /******************************************************************************
393  *        ItemMoniker_Destroy (local function)
394  *******************************************************************************/
395 HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
396 {
397     TRACE("(%p)\n",This);
398
399     if (This->itemName)
400         HeapFree(GetProcessHeap(),0,This->itemName);
401
402     if (This->itemDelimiter)
403         HeapFree(GetProcessHeap(),0,This->itemDelimiter);
404
405     HeapFree(GetProcessHeap(),0,This);
406
407     return S_OK;
408 }
409
410 /******************************************************************************
411  *                  ItemMoniker_BindToObject
412  ******************************************************************************/
413 HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
414                                             IBindCtx* pbc,
415                                             IMoniker* pmkToLeft,
416                                             REFIID riid,
417                                             VOID** ppvResult)
418 {
419     ICOM_THIS(ItemMonikerImpl,iface);
420     
421     HRESULT   res;
422     IID    refid=IID_IOleItemContainer;
423     IOleItemContainer *poic=0;
424
425     TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
426
427     if(ppvResult ==NULL)
428         return E_POINTER;
429
430     if(pmkToLeft==NULL)
431         return E_INVALIDARG;
432
433     *ppvResult=0;
434
435     res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
436
437     if (SUCCEEDED(res)){
438
439         res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);
440
441         IOleItemContainer_Release(poic);
442     }
443
444     return res;
445 }
446
447 /******************************************************************************
448  *        ItemMoniker_BindToStorage
449  ******************************************************************************/
450 HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
451                                              IBindCtx* pbc,
452                                              IMoniker* pmkToLeft,
453                                              REFIID riid,
454                                              VOID** ppvResult)
455 {
456     ICOM_THIS(ItemMonikerImpl,iface);
457
458     HRESULT   res;
459     IOleItemContainer *poic=0;
460
461     TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
462
463     *ppvResult=0;
464
465     if(pmkToLeft==NULL)
466         return E_INVALIDARG;
467         
468     res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
469
470     if (SUCCEEDED(res)){
471
472         res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);
473
474         IOleItemContainer_Release(poic);
475     }
476
477     return res;
478 }
479
480 /******************************************************************************
481  *        ItemMoniker_Reduce
482  ******************************************************************************/
483 HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
484                                       IBindCtx* pbc,
485                                       DWORD dwReduceHowFar,
486                                       IMoniker** ppmkToLeft,
487                                       IMoniker** ppmkReduced)
488 {
489     TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
490
491     if (ppmkReduced==NULL)
492         return E_POINTER;
493
494     ItemMonikerImpl_AddRef(iface);
495
496     *ppmkReduced=iface;
497     
498     return MK_S_REDUCED_TO_SELF;
499 }
500 /******************************************************************************
501  *        ItemMoniker_ComposeWith
502  ******************************************************************************/
503 HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
504                                            IMoniker* pmkRight,
505                                            BOOL fOnlyIfNotGeneric,
506                                            IMoniker** ppmkComposite)
507 {
508     HRESULT res=S_OK;
509     DWORD mkSys,mkSys2;
510     IEnumMoniker* penumMk=0;
511     IMoniker *pmostLeftMk=0;
512     IMoniker* tempMkComposite=0;
513
514     TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
515
516     if ((ppmkComposite==NULL)||(pmkRight==NULL))
517         return E_POINTER;
518
519     *ppmkComposite=0;
520     
521     IMoniker_IsSystemMoniker(pmkRight,&mkSys);
522
523     /* If pmkRight is an anti-moniker, the returned moniker is NULL */
524     if(mkSys==MKSYS_ANTIMONIKER)
525         return res;
526
527     else
528         /* if pmkRight is a composite whose leftmost component is an anti-moniker,           */
529         /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
530         
531          if(mkSys==MKSYS_GENERICCOMPOSITE){
532
533             res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
534
535             if (FAILED(res))
536                 return res;
537
538             res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
539
540             IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
541
542             if(mkSys2==MKSYS_ANTIMONIKER){
543
544                 IMoniker_Release(pmostLeftMk);
545
546                 tempMkComposite=iface;
547                 IMoniker_AddRef(iface);
548                 
549                 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
550
551                     res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
552
553                     IMoniker_Release(tempMkComposite);
554                     IMoniker_Release(pmostLeftMk);
555
556                     tempMkComposite=*ppmkComposite;
557                     IMoniker_AddRef(tempMkComposite);
558 }
559                 return res;
560             }
561             else
562                 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
563          }
564          /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
565           composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
566           a NULL moniker and a return value of MK_E_NEEDGENERIC */
567           else
568             if (!fOnlyIfNotGeneric)
569                 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
570
571             else
572                 return MK_E_NEEDGENERIC;
573 }
574
575 /******************************************************************************
576  *        ItemMoniker_Enum
577  ******************************************************************************/
578 HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
579 {
580     TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
581
582     if (ppenumMoniker == NULL)
583         return E_POINTER;
584
585     *ppenumMoniker = NULL;
586
587     return S_OK;
588 }
589
590 /******************************************************************************
591  *        ItemMoniker_IsEqual
592  ******************************************************************************/
593 HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
594 {
595
596     CLSID clsid;
597     LPOLESTR dispName1,dispName2;
598     IBindCtx* bind;
599     HRESULT res;
600
601     TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
602
603     if (pmkOtherMoniker==NULL)
604         return S_FALSE;
605     
606     /* This method returns S_OK if both monikers are item monikers and their display names are */
607     /* identical (using a case-insensitive comparison); otherwise, the method returns S_FALSE. */
608
609     IMoniker_GetClassID(pmkOtherMoniker,&clsid);
610
611     if (!IsEqualCLSID(&clsid,&CLSID_ItemMoniker))
612         return S_FALSE;
613
614     res=CreateBindCtx(0,&bind);
615     if (FAILED(res))
616         return res;
617
618     IMoniker_GetDisplayName(iface,bind,NULL,&dispName1);
619     IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2);
620     
621     if (lstrcmpW(dispName1,dispName2)!=0)
622         return S_FALSE;
623     
624     return S_OK;
625 }
626
627 /******************************************************************************
628  *        ItemMoniker_Hash
629  ******************************************************************************/
630 HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
631 {
632     ICOM_THIS(ItemMonikerImpl,iface);
633
634     int  h = 0,i,skip,len;
635     int  off = 0;
636     LPOLESTR val;
637
638     if (pdwHash==NULL)
639         return E_POINTER;
640     
641     val =  This->itemName;
642     len = lstrlenW(val);
643
644     if (len < 16) {
645         for (i = len ; i > 0; i--) {
646             h = (h * 37) + val[off++];
647 }
648     } else {
649         /* only sample some characters */
650         skip = len / 8;
651         for (i = len ; i > 0; i -= skip, off += skip) {
652             h = (h * 39) + val[off];
653         }
654     }
655
656     *pdwHash=h;
657
658     return S_OK;
659 }
660
661 /******************************************************************************
662  *        ItemMoniker_IsRunning
663  ******************************************************************************/
664 HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
665                                          IBindCtx* pbc,
666                                          IMoniker* pmkToLeft,
667                                          IMoniker* pmkNewlyRunning)
668 {
669     IRunningObjectTable* rot;
670     HRESULT res;
671     IOleItemContainer *poic=0;
672     ICOM_THIS(ItemMonikerImpl,iface);
673
674     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
675
676     /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
677     /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running.              */
678     if (pmkToLeft==NULL)
679         if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
680             return S_OK;
681         else {
682             if (pbc==NULL)
683                 return E_POINTER;
684
685             res=IBindCtx_GetRunningObjectTable(pbc,&rot);
686
687             if (FAILED(res))
688                 return res;
689
690             res = IRunningObjectTable_IsRunning(rot,iface);
691
692             IRunningObjectTable_Release(rot);
693         }
694     else{
695
696         /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter,         */
697         /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
698         /* passing the string contained within this moniker. */
699         
700         res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
701
702         if (SUCCEEDED(res)){
703
704             res=IOleItemContainer_IsRunning(poic,This->itemName);
705
706             IOleItemContainer_Release(poic);
707         }
708     }
709
710     return res;
711 }
712
713 /******************************************************************************
714  *        ItemMoniker_GetTimeOfLastChange
715  ******************************************************************************/
716 HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
717                                                    IBindCtx* pbc,
718                                                    IMoniker* pmkToLeft,
719                                                    FILETIME* pItemTime)
720 {
721     IRunningObjectTable* rot;
722     HRESULT res;
723     IMoniker *compositeMk;
724
725     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
726
727     if (pItemTime==NULL)
728         return E_INVALIDARG;
729
730     /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
731     if (pmkToLeft==NULL)
732
733         return MK_E_NOTBINDABLE;
734     else {
735
736         /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access  */
737         /* the time of last change. If the object is not in the ROT, the method calls                          */
738         /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter.                                            */
739
740         res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
741
742         res=IBindCtx_GetRunningObjectTable(pbc,&rot);
743
744         if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
745
746             res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
747
748         IMoniker_Release(compositeMk);
749 }
750
751     return res;
752 }
753
754 /******************************************************************************
755  *        ItemMoniker_Inverse
756  ******************************************************************************/
757 HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
758 {
759     TRACE("(%p,%p)\n",iface,ppmk);
760
761     if (ppmk==NULL)
762         return E_POINTER;
763
764     return CreateAntiMoniker(ppmk);
765 }
766
767 /******************************************************************************
768  *        ItemMoniker_CommonPrefixWith
769  ******************************************************************************/
770 HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
771 {
772     DWORD mkSys;
773     IMoniker_IsSystemMoniker(pmkOther,&mkSys);
774     /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
775     /* to this moniker and returns MK_S_US */
776
777     if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
778
779         *ppmkPrefix=iface;
780         
781         IMoniker_AddRef(iface);
782         
783         return MK_S_US;
784     }
785     else
786         /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
787         /* the case where the other moniker is a generic composite. */
788         return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
789 }
790
791 /******************************************************************************
792  *        ItemMoniker_RelativePathTo
793  ******************************************************************************/
794 HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
795 {
796     TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
797
798     if (ppmkRelPath==NULL)
799         return E_POINTER;
800
801     *ppmkRelPath=0;
802     
803     return MK_E_NOTBINDABLE;
804 }
805
806 /******************************************************************************
807  *        ItemMoniker_GetDisplayName
808  ******************************************************************************/
809 HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
810                                               IBindCtx* pbc,
811                                               IMoniker* pmkToLeft,
812                                               LPOLESTR *ppszDisplayName)
813 {
814     ICOM_THIS(ItemMonikerImpl,iface);
815
816     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
817
818     if (ppszDisplayName==NULL)
819         return E_POINTER;
820
821     if (pmkToLeft!=NULL){
822         return E_INVALIDARG;
823     }
824
825     *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));
826
827     if (*ppszDisplayName==NULL)
828         return E_OUTOFMEMORY;
829
830     strcpyW(*ppszDisplayName,This->itemDelimiter);
831     strcatW(*ppszDisplayName,This->itemName);
832     
833     return S_OK;
834 }
835
836 /******************************************************************************
837  *        ItemMoniker_ParseDisplayName
838  ******************************************************************************/
839 HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
840                                                 IBindCtx* pbc,
841                                                 IMoniker* pmkToLeft,
842                                                 LPOLESTR pszDisplayName,
843                                                 ULONG* pchEaten,
844                                                 IMoniker** ppmkOut)
845 {
846     IOleItemContainer* poic=0;
847     IParseDisplayName* ppdn=0;
848     LPOLESTR displayName;
849     HRESULT res;
850     ICOM_THIS(ItemMonikerImpl,iface);
851
852     /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
853     if (pmkToLeft==NULL)
854
855         return MK_E_SYNTAX;
856
857     else{
858         /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
859         /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */        /* name to IParseDisplayName::ParseDisplayName */
860         res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
861
862         if (SUCCEEDED(res)){
863
864             res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
865
866             res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);
867
868             res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);
869
870             IOleItemContainer_Release(poic);
871             IParseDisplayName_Release(ppdn);
872         }
873 }
874     return res;
875 }
876
877 /******************************************************************************
878  *        ItemMoniker_IsSystemMonker
879  ******************************************************************************/
880 HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
881 {
882     TRACE("(%p,%p)\n",iface,pwdMksys);
883
884     if (!pwdMksys)
885         return E_POINTER;
886     
887     (*pwdMksys)=MKSYS_ITEMMONIKER;
888
889     return S_OK;
890 }
891
892 /*******************************************************************************
893  *        ItemMonikerIROTData_QueryInterface
894  *******************************************************************************/
895 HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
896 {
897
898     ICOM_THIS_From_IROTData(IMoniker, iface);
899
900     TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
901
902     return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);
903 }
904
905 /***********************************************************************
906  *        ItemMonikerIROTData_AddRef
907  */
908 ULONG   WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
909 {
910     ICOM_THIS_From_IROTData(IMoniker, iface);
911
912     TRACE("(%p)\n",iface);
913
914     return ItemMonikerImpl_AddRef(This);
915 }
916
917 /***********************************************************************
918  *        ItemMonikerIROTData_Release
919  */
920 ULONG   WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
921 {
922     ICOM_THIS_From_IROTData(IMoniker, iface);
923     
924     TRACE("(%p)\n",iface);
925
926     return ItemMonikerImpl_Release(This);
927 }
928
929 /******************************************************************************
930  *        ItemMonikerIROTData_GetComparaisonData
931  ******************************************************************************/
932 HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
933                                                          BYTE* pbData,
934                                                          ULONG cbMax,
935                                                          ULONG* pcbData)
936 {
937     FIXME("(),stub!\n");
938     return E_NOTIMPL;
939 }
940
941 /******************************************************************************
942  *        CreateItemMoniker16   [OLE2.28]
943  ******************************************************************************/
944 HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim,LPCOLESTR  lpszItem,LPMONIKER* ppmk)
945 {
946
947     FIXME("(%s,%p),stub!\n",lpszDelim,ppmk);
948     *ppmk = NULL;
949     return E_NOTIMPL;
950 }
951
952 /******************************************************************************
953  *        CreateItemMoniker     [OLE.55]
954  ******************************************************************************/
955 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR  lpszItem, LPMONIKER * ppmk)
956 {
957     ItemMonikerImpl* newItemMoniker = 0;
958     HRESULT        hr = S_OK;
959     IID riid=IID_IMoniker;
960
961     TRACE("(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk);
962
963     newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
964
965     if (newItemMoniker == 0)
966         return STG_E_INSUFFICIENTMEMORY;
967
968     hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
969
970     if (FAILED(hr)){
971
972         HeapFree(GetProcessHeap(),0,newItemMoniker);
973     return hr;
974     }
975
976     return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk);
977 }