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