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