Fixed a char/NULL comparison.
[wine/testsucceed.git] / dlls / ole32 / itemmoniker.c
bloba2c9171294ba955b32362bc1d00108787a81fdc6
1 /***************************************************************************************
2 * ItemMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
7 #include <assert.h>
8 #include "winerror.h"
9 #include "winbase.h"
10 #include "debugtools.h"
11 #include "wine/winestring.h"
12 #include "wine/obj_base.h"
13 #include "wine/obj_misc.h"
14 #include "wine/obj_storage.h"
15 #include "wine/obj_moniker.h"
16 #include "wine/obj_inplace.h"
17 #include "wine/unicode.h"
19 DEFAULT_DEBUG_CHANNEL(ole);
21 /* ItemMoniker data structure */
22 typedef struct ItemMonikerImpl{
24 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
26 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
27 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
29 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
31 ULONG ref; /* reference counter for this object */
33 LPOLESTR itemName; /* item name identified by this ItemMoniker */
35 LPOLESTR itemDelimiter; /* Delimiter string */
37 } ItemMonikerImpl;
39 /********************************************************************************/
40 /* ItemMoniker prototype functions : */
42 /* IUnknown prototype functions */
43 static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
44 static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface);
45 static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface);
47 /* IPersist prototype functions */
48 static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
50 /* IPersistStream prototype functions */
51 static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface);
52 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface, IStream* pStm);
53 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
54 static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
56 /* IMoniker prototype functions */
57 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
58 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
59 static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
60 static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
61 static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
62 static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
63 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
64 static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
65 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime);
66 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
67 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
68 static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
69 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
70 static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
71 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
73 /* Local function used by ItemMoniker implementation */
74 HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszPathName);
75 HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
77 /********************************************************************************/
78 /* IROTData prototype functions */
80 /* IUnknown prototype functions */
81 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
82 static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface);
83 static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface);
85 /* IROTData prototype function */
86 static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
88 /********************************************************************************/
89 /* Virtual function table for the ItemMonikerImpl class witch include Ipersist,*/
90 /* IPersistStream and IMoniker functions. */
91 static ICOM_VTABLE(IMoniker) VT_ItemMonikerImpl =
93 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
94 ItemMonikerImpl_QueryInterface,
95 ItemMonikerImpl_AddRef,
96 ItemMonikerImpl_Release,
97 ItemMonikerImpl_GetClassID,
98 ItemMonikerImpl_IsDirty,
99 ItemMonikerImpl_Load,
100 ItemMonikerImpl_Save,
101 ItemMonikerImpl_GetSizeMax,
102 ItemMonikerImpl_BindToObject,
103 ItemMonikerImpl_BindToStorage,
104 ItemMonikerImpl_Reduce,
105 ItemMonikerImpl_ComposeWith,
106 ItemMonikerImpl_Enum,
107 ItemMonikerImpl_IsEqual,
108 ItemMonikerImpl_Hash,
109 ItemMonikerImpl_IsRunning,
110 ItemMonikerImpl_GetTimeOfLastChange,
111 ItemMonikerImpl_Inverse,
112 ItemMonikerImpl_CommonPrefixWith,
113 ItemMonikerImpl_RelativePathTo,
114 ItemMonikerImpl_GetDisplayName,
115 ItemMonikerImpl_ParseDisplayName,
116 ItemMonikerImpl_IsSystemMoniker
119 /********************************************************************************/
120 /* Virtual function table for the IROTData class. */
121 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
123 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
124 ItemMonikerROTDataImpl_QueryInterface,
125 ItemMonikerROTDataImpl_AddRef,
126 ItemMonikerROTDataImpl_Release,
127 ItemMonikerROTDataImpl_GetComparaisonData
130 /*******************************************************************************
131 * ItemMoniker_QueryInterface
132 *******************************************************************************/
133 HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
135 ICOM_THIS(ItemMonikerImpl,iface);
137 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
139 /* Perform a sanity check on the parameters.*/
140 if ( (This==0) || (ppvObject==0) )
141 return E_INVALIDARG;
143 /* Initialize the return parameter */
144 *ppvObject = 0;
146 /* Compare the riid with the interface IDs implemented by this object.*/
147 if (IsEqualIID(&IID_IUnknown, riid) ||
148 IsEqualIID(&IID_IPersist, riid) ||
149 IsEqualIID(&IID_IPersistStream, riid) ||
150 IsEqualIID(&IID_IMoniker, riid)
152 *ppvObject = iface;
154 else if (IsEqualIID(&IID_IROTData, riid))
155 *ppvObject = (IROTData*)&(This->lpvtbl2);
157 /* Check that we obtained an interface.*/
158 if ((*ppvObject)==0)
159 return E_NOINTERFACE;
161 /* Query Interface always increases the reference count by one when it is successful */
162 ItemMonikerImpl_AddRef(iface);
164 return S_OK;
167 /******************************************************************************
168 * ItemMoniker_AddRef
169 ******************************************************************************/
170 ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
172 ICOM_THIS(ItemMonikerImpl,iface);
174 TRACE("(%p)\n",This);
176 return ++(This->ref);
179 /******************************************************************************
180 * ItemMoniker_Release
181 ******************************************************************************/
182 ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
184 ICOM_THIS(ItemMonikerImpl,iface);
186 TRACE("(%p)\n",This);
188 This->ref--;
190 /* destroy the object if there's no more reference on it */
191 if (This->ref==0){
193 ItemMonikerImpl_Destroy(This);
195 return 0;
197 return This->ref;;
200 /******************************************************************************
201 * ItemMoniker_GetClassID
202 ******************************************************************************/
203 HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
205 TRACE("(%p,%p),stub!\n",iface,pClassID);
207 if (pClassID==NULL)
208 return E_POINTER;
210 *pClassID = CLSID_ItemMoniker;
212 return S_OK;
215 /******************************************************************************
216 * ItemMoniker_IsDirty
217 ******************************************************************************/
218 HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
220 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
221 method in the OLE-provided moniker interfaces always return S_FALSE because
222 their internal state never changes. */
224 TRACE("(%p)\n",iface);
226 return S_FALSE;
229 /******************************************************************************
230 * ItemMoniker_Load
231 ******************************************************************************/
232 HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
235 ICOM_THIS(ItemMonikerImpl,iface);
236 HRESULT res;
237 DWORD delimiterLength,nameLength;
238 CHAR *itemNameA,*itemDelimiterA;
239 ULONG bread;
241 /* for more details about data read by this function see coments of ItemMonikerImpl_Save function */
243 /* read item delimiter string length + 1 */
244 res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);
245 if (bread != sizeof(DWORD))
246 return E_FAIL;
248 /* read item delimiter string */
249 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
250 res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
251 if (bread != delimiterLength)
252 return E_FAIL;
254 This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,delimiterLength*sizeof(WCHAR));
255 if (!This->itemDelimiter)
256 return E_OUTOFMEMORY;
258 lstrcpyAtoW(This->itemDelimiter,itemDelimiterA);
260 /* read item name string length + 1*/
261 res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
262 if (bread != sizeof(DWORD))
263 return E_FAIL;
265 /* read item name string */
266 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
267 res=IStream_Read(pStm,itemNameA,nameLength,&bread);
268 if (bread != nameLength)
269 return E_FAIL;
271 This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,nameLength*sizeof(WCHAR));
272 if (!This->itemName)
273 return E_OUTOFMEMORY;
275 lstrcpyAtoW(This->itemName,itemNameA);
277 return res;
280 /******************************************************************************
281 * ItemMoniker_Save
282 ******************************************************************************/
283 HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,
284 IStream* pStm,/* pointer to the stream where the object is to be saved */
285 BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
287 ICOM_THIS(ItemMonikerImpl,iface);
288 HRESULT res;
289 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
290 DWORD nameLength=lstrlenW(This->itemName)+1;
291 CHAR *itemNameA,*itemDelimiterA;
293 /* data writen by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
294 /* 2) String (type A): item delimiter string ('\0' included) */
295 /* 3) DWORD : size of item name string ('\0' included) */
296 /* 4) String (type A): item name string ('\0' included) */
298 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
299 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
300 lstrcpyWtoA(itemNameA,This->itemName);
301 lstrcpyWtoA(itemDelimiterA,This->itemDelimiter);
303 res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
304 res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
305 res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
306 res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);
308 return res;
311 /******************************************************************************
312 * ItemMoniker_GetSizeMax
313 ******************************************************************************/
314 HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,
315 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
317 ICOM_THIS(ItemMonikerImpl,iface);
318 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
319 DWORD nameLength=lstrlenW(This->itemName)+1;
321 TRACE("(%p,%p)\n",iface,pcbSize);
323 if (pcbSize!=NULL)
324 return E_POINTER;
326 /* for more details see ItemMonikerImpl_Save coments */
328 pcbSize->s.LowPart = sizeof(DWORD) + /* DWORD witch contains delimiter length */
329 delimiterLength + /* item delimiter string */
330 sizeof(DWORD) + /* DWORD witch contains item name length */
331 nameLength + /* item name string */
332 34; /* this constant was added ! because when I tested this function it usually */
333 /* returns 34 bytes more than the number of bytes used by IMoniker::Save function */
334 pcbSize->s.HighPart=0;
336 return S_OK;
339 /******************************************************************************
340 * ItemMoniker_Construct (local function)
341 *******************************************************************************/
342 HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
345 int sizeStr1=lstrlenW(lpszItem);
346 int sizeStr2=lstrlenW(lpszDelim);
348 TRACE("(%p,%p)\n",This,lpszItem);
350 /* Initialize the virtual fgunction table. */
351 This->lpvtbl1 = &VT_ItemMonikerImpl;
352 This->lpvtbl2 = &VT_ROTDataImpl;
353 This->ref = 0;
355 This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
356 This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
358 if ((This->itemName==NULL)||(This->itemDelimiter==NULL))
359 return E_OUTOFMEMORY;
361 strcpyW(This->itemName,lpszItem);
362 strcpyW(This->itemDelimiter,lpszDelim);
364 return S_OK;
367 /******************************************************************************
368 * ItemMoniker_Destroy (local function)
369 *******************************************************************************/
370 HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
372 TRACE("(%p)\n",This);
374 if (This->itemName)
375 HeapFree(GetProcessHeap(),0,This->itemName);
377 if (This->itemDelimiter)
378 HeapFree(GetProcessHeap(),0,This->itemDelimiter);
380 HeapFree(GetProcessHeap(),0,This);
382 return S_OK;
385 /******************************************************************************
386 * ItemMoniker_BindToObject
387 ******************************************************************************/
388 HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
389 IBindCtx* pbc,
390 IMoniker* pmkToLeft,
391 REFIID riid,
392 VOID** ppvResult)
394 ICOM_THIS(ItemMonikerImpl,iface);
396 HRESULT res;
397 IID refid=IID_IOleItemContainer;
398 IOleItemContainer *poic=0;
400 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
402 if(ppvResult ==NULL)
403 return E_POINTER;
405 if(pmkToLeft==NULL)
406 return E_INVALIDARG;
408 *ppvResult=0;
410 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
412 if (SUCCEEDED(res)){
414 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);
416 IOleItemContainer_Release(poic);
419 return res;
422 /******************************************************************************
423 * ItemMoniker_BindToStorage
424 ******************************************************************************/
425 HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
426 IBindCtx* pbc,
427 IMoniker* pmkToLeft,
428 REFIID riid,
429 VOID** ppvResult)
431 ICOM_THIS(ItemMonikerImpl,iface);
433 HRESULT res;
434 IOleItemContainer *poic=0;
436 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
438 *ppvResult=0;
440 if(pmkToLeft==NULL)
441 return E_INVALIDARG;
443 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
445 if (SUCCEEDED(res)){
447 res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);
449 IOleItemContainer_Release(poic);
452 return res;
455 /******************************************************************************
456 * ItemMoniker_Reduce
457 ******************************************************************************/
458 HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
459 IBindCtx* pbc,
460 DWORD dwReduceHowFar,
461 IMoniker** ppmkToLeft,
462 IMoniker** ppmkReduced)
464 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
466 if (ppmkReduced==NULL)
467 return E_POINTER;
469 ItemMonikerImpl_AddRef(iface);
471 *ppmkReduced=iface;
473 return MK_S_REDUCED_TO_SELF;
475 /******************************************************************************
476 * ItemMoniker_ComposeWith
477 ******************************************************************************/
478 HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
479 IMoniker* pmkRight,
480 BOOL fOnlyIfNotGeneric,
481 IMoniker** ppmkComposite)
483 HRESULT res=S_OK;
484 DWORD mkSys,mkSys2;
485 IEnumMoniker* penumMk=0;
486 IMoniker *pmostLeftMk=0;
487 IMoniker* tempMkComposite=0;
489 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
491 if ((ppmkComposite==NULL)||(pmkRight==NULL))
492 return E_POINTER;
494 *ppmkComposite=0;
496 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
498 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
499 if(mkSys==MKSYS_ANTIMONIKER)
500 return res;
502 else
503 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
504 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
506 if(mkSys==MKSYS_GENERICCOMPOSITE){
508 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
510 if (FAILED(res))
511 return res;
513 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
515 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
517 if(mkSys2==MKSYS_ANTIMONIKER){
519 IMoniker_Release(pmostLeftMk);
521 tempMkComposite=iface;
522 IMoniker_AddRef(iface);
524 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
526 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
528 IMoniker_Release(tempMkComposite);
529 IMoniker_Release(pmostLeftMk);
531 tempMkComposite=*ppmkComposite;
532 IMoniker_AddRef(tempMkComposite);
534 return res;
536 else
537 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
539 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
540 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
541 a NULL moniker and a return value of MK_E_NEEDGENERIC */
542 else
543 if (!fOnlyIfNotGeneric)
544 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
546 else
547 return MK_E_NEEDGENERIC;
550 /******************************************************************************
551 * ItemMoniker_Enum
552 ******************************************************************************/
553 HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
555 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
557 if (ppenumMoniker == NULL)
558 return E_POINTER;
560 *ppenumMoniker = NULL;
562 return S_OK;
565 /******************************************************************************
566 * ItemMoniker_IsEqual
567 ******************************************************************************/
568 HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
571 CLSID clsid;
572 LPOLESTR dispName1,dispName2;
573 IBindCtx* bind;
574 HRESULT res;
576 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
578 if (pmkOtherMoniker==NULL)
579 return S_FALSE;
581 /* This method returns S_OK if both monikers are item monikers and their display names are */
582 /* identical (using a case-insensitive comparison); otherwise, the method returns S_FALSE. */
584 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
586 if (!IsEqualCLSID(&clsid,&CLSID_ItemMoniker))
587 return S_FALSE;
589 res=CreateBindCtx(0,&bind);
590 if (FAILED(res))
591 return res;
593 IMoniker_GetDisplayName(iface,bind,NULL,&dispName1);
594 IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2);
596 if (lstrcmpW(dispName1,dispName2)!=0)
597 return S_FALSE;
599 return S_OK;
602 /******************************************************************************
603 * ItemMoniker_Hash
604 ******************************************************************************/
605 HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
607 ICOM_THIS(ItemMonikerImpl,iface);
609 int h = 0,i,skip,len;
610 int off = 0;
611 LPOLESTR val;
613 if (pdwHash==NULL)
614 return E_POINTER;
616 val = This->itemName;
617 len = lstrlenW(val);
619 if (len < 16) {
620 for (i = len ; i > 0; i--) {
621 h = (h * 37) + val[off++];
623 } else {
624 /* only sample some characters */
625 skip = len / 8;
626 for (i = len ; i > 0; i -= skip, off += skip) {
627 h = (h * 39) + val[off];
631 *pdwHash=h;
633 return S_OK;
636 /******************************************************************************
637 * ItemMoniker_IsRunning
638 ******************************************************************************/
639 HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
640 IBindCtx* pbc,
641 IMoniker* pmkToLeft,
642 IMoniker* pmkNewlyRunning)
644 IRunningObjectTable* rot;
645 HRESULT res;
646 IOleItemContainer *poic=0;
647 ICOM_THIS(ItemMonikerImpl,iface);
649 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
651 /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
652 /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */
653 if (pmkToLeft==NULL)
654 if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
655 return S_OK;
656 else {
657 if (pbc==NULL)
658 return E_POINTER;
660 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
662 if (FAILED(res))
663 return res;
665 res = IRunningObjectTable_IsRunning(rot,iface);
667 IRunningObjectTable_Release(rot);
669 else{
671 /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */
672 /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
673 /* passing the string contained within this moniker. */
675 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
677 if (SUCCEEDED(res)){
679 res=IOleItemContainer_IsRunning(poic,This->itemName);
681 IOleItemContainer_Release(poic);
685 return res;
688 /******************************************************************************
689 * ItemMoniker_GetTimeOfLastChange
690 ******************************************************************************/
691 HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
692 IBindCtx* pbc,
693 IMoniker* pmkToLeft,
694 FILETIME* pItemTime)
696 IRunningObjectTable* rot;
697 HRESULT res;
698 IMoniker *compositeMk;
700 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
702 if (pItemTime==NULL)
703 return E_INVALIDARG;
705 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
706 if (pmkToLeft==NULL)
708 return MK_E_NOTBINDABLE;
709 else {
711 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
712 /* the time of last change. If the object is not in the ROT, the method calls */
713 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
715 res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
717 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
719 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
721 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
723 IMoniker_Release(compositeMk);
726 return res;
729 /******************************************************************************
730 * ItemMoniker_Inverse
731 ******************************************************************************/
732 HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
734 TRACE("(%p,%p)\n",iface,ppmk);
736 if (ppmk==NULL)
737 return E_POINTER;
739 return CreateAntiMoniker(ppmk);
742 /******************************************************************************
743 * ItemMoniker_CommonPrefixWith
744 ******************************************************************************/
745 HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
747 DWORD mkSys;
748 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
749 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
750 /* to this moniker and returns MK_S_US */
752 if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
754 *ppmkPrefix=iface;
756 IMoniker_AddRef(iface);
758 return MK_S_US;
760 else
761 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
762 /* the case where the other moniker is a generic composite. */
763 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
766 /******************************************************************************
767 * ItemMoniker_RelativePathTo
768 ******************************************************************************/
769 HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
771 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
773 if (ppmkRelPath==NULL)
774 return E_POINTER;
776 *ppmkRelPath=0;
778 return MK_E_NOTBINDABLE;
781 /******************************************************************************
782 * ItemMoniker_GetDisplayName
783 ******************************************************************************/
784 HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
785 IBindCtx* pbc,
786 IMoniker* pmkToLeft,
787 LPOLESTR *ppszDisplayName)
789 ICOM_THIS(ItemMonikerImpl,iface);
791 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
793 if (ppszDisplayName==NULL)
794 return E_POINTER;
796 if (pmkToLeft!=NULL){
797 return E_INVALIDARG;
800 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));
802 if (*ppszDisplayName==NULL)
803 return E_OUTOFMEMORY;
805 strcpyW(*ppszDisplayName,This->itemDelimiter);
806 strcatW(*ppszDisplayName,This->itemName);
808 return S_OK;
811 /******************************************************************************
812 * ItemMoniker_ParseDisplayName
813 ******************************************************************************/
814 HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
815 IBindCtx* pbc,
816 IMoniker* pmkToLeft,
817 LPOLESTR pszDisplayName,
818 ULONG* pchEaten,
819 IMoniker** ppmkOut)
821 IOleItemContainer* poic=0;
822 IParseDisplayName* ppdn=0;
823 LPOLESTR displayName;
824 HRESULT res;
825 ICOM_THIS(ItemMonikerImpl,iface);
827 /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
828 if (pmkToLeft==NULL)
830 return MK_E_SYNTAX;
832 else{
833 /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
834 /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */ /* name to IParseDisplayName::ParseDisplayName */
835 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
837 if (SUCCEEDED(res)){
839 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
841 res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);
843 res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);
845 IOleItemContainer_Release(poic);
846 IParseDisplayName_Release(ppdn);
849 return res;
852 /******************************************************************************
853 * ItemMoniker_IsSystemMonker
854 ******************************************************************************/
855 HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
857 TRACE("(%p,%p)\n",iface,pwdMksys);
859 if (!pwdMksys)
860 return E_POINTER;
862 (*pwdMksys)=MKSYS_ITEMMONIKER;
864 return S_OK;
867 /*******************************************************************************
868 * ItemMonikerIROTData_QueryInterface
869 *******************************************************************************/
870 HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
873 ICOM_THIS_From_IROTData(IMoniker, iface);
875 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
877 return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);
880 /***********************************************************************
881 * ItemMonikerIROTData_AddRef
883 ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
885 ICOM_THIS_From_IROTData(IMoniker, iface);
887 TRACE("(%p)\n",iface);
889 return ItemMonikerImpl_AddRef(This);
892 /***********************************************************************
893 * ItemMonikerIROTData_Release
895 ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
897 ICOM_THIS_From_IROTData(IMoniker, iface);
899 TRACE("(%p)\n",iface);
901 return ItemMonikerImpl_Release(This);
904 /******************************************************************************
905 * ItemMonikerIROTData_GetComparaisonData
906 ******************************************************************************/
907 HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
908 BYTE* pbData,
909 ULONG cbMax,
910 ULONG* pcbData)
912 FIXME("(),stub!\n");
913 return E_NOTIMPL;
916 /******************************************************************************
917 * CreateItemMoniker16 [OLE2.28]
918 ******************************************************************************/
919 HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim,LPCOLESTR lpszItem,LPMONIKER* ppmk)
922 FIXME("(%s,%p),stub!\n",lpszDelim,ppmk);
923 *ppmk = NULL;
924 return E_NOTIMPL;
927 /******************************************************************************
928 * CreateItemMoniker [OLE.55]
929 ******************************************************************************/
930 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk)
932 ItemMonikerImpl* newItemMoniker = 0;
933 HRESULT hr = S_OK;
934 IID riid=IID_IMoniker;
936 TRACE("(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk);
938 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
940 if (newItemMoniker == 0)
941 return STG_E_INSUFFICIENTMEMORY;
943 hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
945 if (FAILED(hr)){
947 HeapFree(GetProcessHeap(),0,newItemMoniker);
948 return hr;
951 return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk);