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