Added support for anonymous structs/unions on compilers that implement it.
[wine.git] / ole / itemmoniker.c
blobd21a37dc73cf79afab5bfc2cc0755c06119fd161
1 /***************************************************************************************
2 * ItemMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
7 #include "wine/obj_base.h"
8 #include "wine/obj_moniker.h"
9 #include "winbase.h"
11 #include <assert.h>
12 #include "winerror.h"
13 #include "debugtools.h"
14 #include "wine/obj_inplace.h"
16 DEFAULT_DEBUG_CHANNEL(ole)
18 /* ItemMoniker data structure */
19 typedef struct ItemMonikerImpl{
21 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
23 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
24 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
26 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
28 ULONG ref; /* reference counter for this object */
30 LPOLESTR itemName; /* item name identified by this ItemMoniker */
32 LPOLESTR itemDelimiter; /* Delimiter string */
34 } ItemMonikerImpl;
36 /********************************************************************************/
37 /* ItemMoniker prototype functions : */
39 /* IUnknown prototype functions */
40 static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
41 static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface);
42 static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface);
44 /* IPersist prototype functions */
45 static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
47 /* IPersistStream prototype functions */
48 static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface);
49 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface, IStream* pStm);
50 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
51 static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
53 /* IMoniker prototype functions */
54 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
55 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
56 static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
57 static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
58 static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
59 static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
60 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
61 static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
62 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime);
63 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
64 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
65 static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
66 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
67 static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
68 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
70 /* Local function used by ItemMoniker implementation */
71 HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszPathName);
72 HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
74 /********************************************************************************/
75 /* IROTData prototype functions */
77 /* IUnknown prototype functions */
78 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
79 static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface);
80 static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface);
82 /* IROTData prototype function */
83 static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
85 /********************************************************************************/
86 /* Virtual function table for the ItemMonikerImpl class witch include Ipersist,*/
87 /* IPersistStream and IMoniker functions. */
88 static ICOM_VTABLE(IMoniker) VT_ItemMonikerImpl =
90 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
91 ItemMonikerImpl_QueryInterface,
92 ItemMonikerImpl_AddRef,
93 ItemMonikerImpl_Release,
94 ItemMonikerImpl_GetClassID,
95 ItemMonikerImpl_IsDirty,
96 ItemMonikerImpl_Load,
97 ItemMonikerImpl_Save,
98 ItemMonikerImpl_GetSizeMax,
99 ItemMonikerImpl_BindToObject,
100 ItemMonikerImpl_BindToStorage,
101 ItemMonikerImpl_Reduce,
102 ItemMonikerImpl_ComposeWith,
103 ItemMonikerImpl_Enum,
104 ItemMonikerImpl_IsEqual,
105 ItemMonikerImpl_Hash,
106 ItemMonikerImpl_IsRunning,
107 ItemMonikerImpl_GetTimeOfLastChange,
108 ItemMonikerImpl_Inverse,
109 ItemMonikerImpl_CommonPrefixWith,
110 ItemMonikerImpl_RelativePathTo,
111 ItemMonikerImpl_GetDisplayName,
112 ItemMonikerImpl_ParseDisplayName,
113 ItemMonikerImpl_IsSystemMoniker
116 /********************************************************************************/
117 /* Virtual function table for the IROTData class. */
118 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
120 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
121 ItemMonikerROTDataImpl_QueryInterface,
122 ItemMonikerROTDataImpl_AddRef,
123 ItemMonikerROTDataImpl_Release,
124 ItemMonikerROTDataImpl_GetComparaisonData
127 /*******************************************************************************
128 * ItemMoniker_QueryInterface
129 *******************************************************************************/
130 HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
132 ICOM_THIS(ItemMonikerImpl,iface);
134 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
136 /* Perform a sanity check on the parameters.*/
137 if ( (This==0) || (ppvObject==0) )
138 return E_INVALIDARG;
140 /* Initialize the return parameter */
141 *ppvObject = 0;
143 /* Compare the riid with the interface IDs implemented by this object.*/
144 if (IsEqualIID(&IID_IUnknown, riid) ||
145 IsEqualIID(&IID_IPersist, riid) ||
146 IsEqualIID(&IID_IPersistStream, riid) ||
147 IsEqualIID(&IID_IMoniker, riid)
149 *ppvObject = iface;
151 else if (IsEqualIID(&IID_IROTData, riid))
152 *ppvObject = (IROTData*)&(This->lpvtbl2);
154 /* Check that we obtained an interface.*/
155 if ((*ppvObject)==0)
156 return E_NOINTERFACE;
158 /* Query Interface always increases the reference count by one when it is successful */
159 ItemMonikerImpl_AddRef(iface);
161 return S_OK;
164 /******************************************************************************
165 * ItemMoniker_AddRef
166 ******************************************************************************/
167 ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
169 ICOM_THIS(ItemMonikerImpl,iface);
171 TRACE("(%p)\n",This);
173 return ++(This->ref);
176 /******************************************************************************
177 * ItemMoniker_Release
178 ******************************************************************************/
179 ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
181 ICOM_THIS(ItemMonikerImpl,iface);
183 TRACE("(%p)\n",This);
185 This->ref--;
187 /* destroy the object if there's no more reference on it */
188 if (This->ref==0){
190 ItemMonikerImpl_Destroy(This);
192 return 0;
194 return This->ref;;
197 /******************************************************************************
198 * ItemMoniker_GetClassID
199 ******************************************************************************/
200 HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
202 TRACE("(%p,%p),stub!\n",iface,pClassID);
204 if (pClassID==NULL)
205 return E_POINTER;
207 *pClassID = CLSID_ItemMoniker;
209 return S_OK;
212 /******************************************************************************
213 * ItemMoniker_IsDirty
214 ******************************************************************************/
215 HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
217 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
218 method in the OLE-provided moniker interfaces always return S_FALSE because
219 their internal state never changes. */
221 TRACE("(%p)\n",iface);
223 return S_FALSE;
226 /******************************************************************************
227 * ItemMoniker_Load
228 ******************************************************************************/
229 HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
232 ICOM_THIS(ItemMonikerImpl,iface);
233 HRESULT res;
234 DWORD delimiterLength,nameLength;
235 CHAR *itemNameA,*itemDelimiterA;
236 ULONG bread;
238 /* for more details about data read by this function see coments of ItemMonikerImpl_Save function */
240 /* read item delimiter string length + 1 */
241 res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);
242 if (bread != sizeof(DWORD))
243 return E_FAIL;
245 /* read item delimiter string */
246 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
247 res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
248 if (bread != delimiterLength)
249 return E_FAIL;
251 This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,delimiterLength*sizeof(WCHAR));
252 if (!This->itemDelimiter)
253 return E_OUTOFMEMORY;
255 lstrcpyAtoW(This->itemDelimiter,itemDelimiterA);
257 /* read item name string length + 1*/
258 res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
259 if (bread != sizeof(DWORD))
260 return E_FAIL;
262 /* read item name string */
263 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
264 res=IStream_Read(pStm,itemNameA,nameLength,&bread);
265 if (bread != nameLength)
266 return E_FAIL;
268 This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,nameLength*sizeof(WCHAR));
269 if (!This->itemName)
270 return E_OUTOFMEMORY;
272 lstrcpyAtoW(This->itemName,itemNameA);
274 return res;
277 /******************************************************************************
278 * ItemMoniker_Save
279 ******************************************************************************/
280 HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,
281 IStream* pStm,/* pointer to the stream where the object is to be saved */
282 BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
284 ICOM_THIS(ItemMonikerImpl,iface);
285 HRESULT res;
286 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
287 DWORD nameLength=lstrlenW(This->itemName)+1;
288 CHAR *itemNameA,*itemDelimiterA;
290 /* data writen by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
291 /* 2) String (type A): item delimiter string ('\0' included) */
292 /* 3) DWORD : size of item name string ('\0' included) */
293 /* 4) String (type A): item name string ('\0' included) */
295 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
296 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
297 lstrcpyWtoA(itemNameA,This->itemName);
298 lstrcpyWtoA(itemDelimiterA,This->itemDelimiter);
300 res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
301 res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
302 res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
303 res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);
305 return res;
308 /******************************************************************************
309 * ItemMoniker_GetSizeMax
310 ******************************************************************************/
311 HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,
312 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
314 ICOM_THIS(ItemMonikerImpl,iface);
315 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
316 DWORD nameLength=lstrlenW(This->itemName)+1;
318 TRACE("(%p,%p)\n",iface,pcbSize);
320 if (pcbSize!=NULL)
321 return E_POINTER;
323 /* for more details see ItemMonikerImpl_Save coments */
325 pcbSize->s.LowPart = sizeof(DWORD) + /* DWORD witch contains delimiter length */
326 delimiterLength + /* item delimiter string */
327 sizeof(DWORD) + /* DWORD witch contains item name length */
328 nameLength + /* item name string */
329 34; /* this constant was added ! because when I tested this function it usually */
330 /* returns 34 bytes more than the number of bytes used by IMoniker::Save function */
331 pcbSize->s.HighPart=0;
333 return S_OK;
336 /******************************************************************************
337 * ItemMoniker_Construct (local function)
338 *******************************************************************************/
339 HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
342 int sizeStr1=lstrlenW(lpszItem);
343 int sizeStr2=lstrlenW(lpszDelim);
345 TRACE("(%p,%p)\n",This,lpszItem);
347 /* Initialize the virtual fgunction table. */
348 This->lpvtbl1 = &VT_ItemMonikerImpl;
349 This->lpvtbl2 = &VT_ROTDataImpl;
350 This->ref = 0;
352 This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
353 This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
355 if ((This->itemName==NULL)||(This->itemDelimiter==NULL))
356 return E_OUTOFMEMORY;
358 lstrcpyW(This->itemName,lpszItem);
359 lstrcpyW(This->itemDelimiter,lpszDelim);
361 return S_OK;
364 /******************************************************************************
365 * ItemMoniker_Destroy (local function)
366 *******************************************************************************/
367 HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
369 TRACE("(%p)\n",This);
371 if (This->itemName)
372 HeapFree(GetProcessHeap(),0,This->itemName);
374 if (This->itemDelimiter)
375 HeapFree(GetProcessHeap(),0,This->itemDelimiter);
377 HeapFree(GetProcessHeap(),0,This);
379 return S_OK;
382 /******************************************************************************
383 * ItemMoniker_BindToObject
384 ******************************************************************************/
385 HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
386 IBindCtx* pbc,
387 IMoniker* pmkToLeft,
388 REFIID riid,
389 VOID** ppvResult)
391 ICOM_THIS(ItemMonikerImpl,iface);
393 HRESULT res;
394 IID refid=IID_IOleItemContainer;
395 IOleItemContainer *poic=0;
397 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
399 if(ppvResult ==NULL)
400 return E_POINTER;
402 if(pmkToLeft==NULL)
403 return E_INVALIDARG;
405 *ppvResult=0;
407 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
409 if (SUCCEEDED(res)){
411 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);
413 IOleItemContainer_Release(poic);
416 return res;
419 /******************************************************************************
420 * ItemMoniker_BindToStorage
421 ******************************************************************************/
422 HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
423 IBindCtx* pbc,
424 IMoniker* pmkToLeft,
425 REFIID riid,
426 VOID** ppvResult)
428 ICOM_THIS(ItemMonikerImpl,iface);
430 HRESULT res;
431 IOleItemContainer *poic=0;
433 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
435 *ppvResult=0;
437 if(pmkToLeft==NULL)
438 return E_INVALIDARG;
440 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
442 if (SUCCEEDED(res)){
444 res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);
446 IOleItemContainer_Release(poic);
449 return res;
452 /******************************************************************************
453 * ItemMoniker_Reduce
454 ******************************************************************************/
455 HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
456 IBindCtx* pbc,
457 DWORD dwReduceHowFar,
458 IMoniker** ppmkToLeft,
459 IMoniker** ppmkReduced)
461 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
463 if (ppmkReduced==NULL)
464 return E_POINTER;
466 ItemMonikerImpl_AddRef(iface);
468 *ppmkReduced=iface;
470 return MK_S_REDUCED_TO_SELF;
472 /******************************************************************************
473 * ItemMoniker_ComposeWith
474 ******************************************************************************/
475 HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
476 IMoniker* pmkRight,
477 BOOL fOnlyIfNotGeneric,
478 IMoniker** ppmkComposite)
480 HRESULT res=S_OK;
481 DWORD mkSys,mkSys2;
482 IEnumMoniker* penumMk=0;
483 IMoniker *pmostLeftMk=0;
484 IMoniker* tempMkComposite=0;
486 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
488 if ((ppmkComposite==NULL)||(pmkRight==NULL))
489 return E_POINTER;
491 *ppmkComposite=0;
493 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
495 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
496 if(mkSys==MKSYS_ANTIMONIKER)
497 return res;
499 else
500 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
501 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
503 if(mkSys==MKSYS_GENERICCOMPOSITE){
505 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
507 if (FAILED(res))
508 return res;
510 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
512 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
514 if(mkSys2==MKSYS_ANTIMONIKER){
516 IMoniker_Release(pmostLeftMk);
518 tempMkComposite=iface;
519 IMoniker_AddRef(iface);
521 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
523 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
525 IMoniker_Release(tempMkComposite);
526 IMoniker_Release(pmostLeftMk);
528 tempMkComposite=*ppmkComposite;
529 IMoniker_AddRef(tempMkComposite);
531 return res;
533 else
534 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
536 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
537 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
538 a NULL moniker and a return value of MK_E_NEEDGENERIC */
539 else
540 if (!fOnlyIfNotGeneric)
541 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
543 else
544 return MK_E_NEEDGENERIC;
547 /******************************************************************************
548 * ItemMoniker_Enum
549 ******************************************************************************/
550 HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
552 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
554 if (ppenumMoniker == NULL)
555 return E_POINTER;
557 *ppenumMoniker = NULL;
559 return S_OK;
562 /******************************************************************************
563 * ItemMoniker_IsEqual
564 ******************************************************************************/
565 HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
568 CLSID clsid;
569 LPOLESTR dispName1,dispName2;
570 IBindCtx* bind;
571 HRESULT res;
573 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
575 if (pmkOtherMoniker==NULL)
576 return S_FALSE;
578 /* This method returns S_OK if both monikers are item monikers and their display names are */
579 /* identical (using a case-insensitive comparison); otherwise, the method returns S_FALSE. */
581 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
583 if (!IsEqualCLSID(&clsid,&CLSID_ItemMoniker))
584 return S_FALSE;
586 res=CreateBindCtx(0,&bind);
587 if (FAILED(res))
588 return res;
590 IMoniker_GetDisplayName(iface,bind,NULL,&dispName1);
591 IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2);
593 if (lstrcmpW(dispName1,dispName2)!=0)
594 return S_FALSE;
596 return S_OK;
599 /******************************************************************************
600 * ItemMoniker_Hash
601 ******************************************************************************/
602 HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
604 ICOM_THIS(ItemMonikerImpl,iface);
606 int h = 0,i,skip,len;
607 int off = 0;
608 LPOLESTR val;
610 if (pdwHash==NULL)
611 return E_POINTER;
613 val = This->itemName;
614 len = lstrlenW(val);
616 if (len < 16) {
617 for (i = len ; i > 0; i--) {
618 h = (h * 37) + val[off++];
620 } else {
621 /* only sample some characters */
622 skip = len / 8;
623 for (i = len ; i > 0; i -= skip, off += skip) {
624 h = (h * 39) + val[off];
628 *pdwHash=h;
630 return S_OK;
633 /******************************************************************************
634 * ItemMoniker_IsRunning
635 ******************************************************************************/
636 HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
637 IBindCtx* pbc,
638 IMoniker* pmkToLeft,
639 IMoniker* pmkNewlyRunning)
641 IRunningObjectTable* rot;
642 HRESULT res;
643 IOleItemContainer *poic=0;
644 ICOM_THIS(ItemMonikerImpl,iface);
646 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
648 /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
649 /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */
650 if (pmkToLeft==NULL)
651 if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
652 return S_OK;
653 else {
654 if (pbc==NULL)
655 return E_POINTER;
657 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
659 if (FAILED(res))
660 return res;
662 res = IRunningObjectTable_IsRunning(rot,iface);
664 IRunningObjectTable_Release(rot);
666 else{
668 /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */
669 /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
670 /* passing the string contained within this moniker. */
672 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
674 if (SUCCEEDED(res)){
676 res=IOleItemContainer_IsRunning(poic,This->itemName);
678 IOleItemContainer_Release(poic);
682 return res;
685 /******************************************************************************
686 * ItemMoniker_GetTimeOfLastChange
687 ******************************************************************************/
688 HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
689 IBindCtx* pbc,
690 IMoniker* pmkToLeft,
691 FILETIME* pItemTime)
693 IRunningObjectTable* rot;
694 HRESULT res;
695 IMoniker *compositeMk;
697 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
699 if (pItemTime==NULL)
700 return E_INVALIDARG;
702 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
703 if (pmkToLeft==NULL)
705 return MK_E_NOTBINDABLE;
706 else {
708 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
709 /* the time of last change. If the object is not in the ROT, the method calls */
710 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
712 res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
714 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
716 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
718 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
720 IMoniker_Release(compositeMk);
723 return res;
726 /******************************************************************************
727 * ItemMoniker_Inverse
728 ******************************************************************************/
729 HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
731 TRACE("(%p,%p)\n",iface,ppmk);
733 if (ppmk==NULL)
734 return E_POINTER;
736 return CreateAntiMoniker(ppmk);
739 /******************************************************************************
740 * ItemMoniker_CommonPrefixWith
741 ******************************************************************************/
742 HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
744 DWORD mkSys;
745 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
746 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
747 /* to this moniker and returns MK_S_US */
749 if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
751 *ppmkPrefix=iface;
753 IMoniker_AddRef(iface);
755 return MK_S_US;
757 else
758 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
759 /* the case where the other moniker is a generic composite. */
760 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
763 /******************************************************************************
764 * ItemMoniker_RelativePathTo
765 ******************************************************************************/
766 HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
768 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
770 if (ppmkRelPath==NULL)
771 return E_POINTER;
773 *ppmkRelPath=0;
775 return MK_E_NOTBINDABLE;
778 /******************************************************************************
779 * ItemMoniker_GetDisplayName
780 ******************************************************************************/
781 HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
782 IBindCtx* pbc,
783 IMoniker* pmkToLeft,
784 LPOLESTR *ppszDisplayName)
786 ICOM_THIS(ItemMonikerImpl,iface);
788 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
790 if (ppszDisplayName==NULL)
791 return E_POINTER;
793 if (pmkToLeft!=NULL){
794 return E_INVALIDARG;
797 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));
799 if (*ppszDisplayName==NULL)
800 return E_OUTOFMEMORY;
802 lstrcpyW(*ppszDisplayName,This->itemDelimiter);
803 lstrcatW(*ppszDisplayName,This->itemName);
805 return S_OK;
808 /******************************************************************************
809 * ItemMoniker_ParseDisplayName
810 ******************************************************************************/
811 HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
812 IBindCtx* pbc,
813 IMoniker* pmkToLeft,
814 LPOLESTR pszDisplayName,
815 ULONG* pchEaten,
816 IMoniker** ppmkOut)
818 IOleItemContainer* poic=0;
819 IParseDisplayName* ppdn=0;
820 LPOLESTR displayName;
821 HRESULT res;
822 ICOM_THIS(ItemMonikerImpl,iface);
824 /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
825 if (pmkToLeft==NULL)
827 return MK_E_SYNTAX;
829 else{
830 /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
831 /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */ /* name to IParseDisplayName::ParseDisplayName */
832 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
834 if (SUCCEEDED(res)){
836 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
838 res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);
840 res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);
842 IOleItemContainer_Release(poic);
843 IParseDisplayName_Release(ppdn);
846 return res;
849 /******************************************************************************
850 * ItemMoniker_IsSystemMonker
851 ******************************************************************************/
852 HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
854 TRACE("(%p,%p)\n",iface,pwdMksys);
856 if (!pwdMksys)
857 return E_POINTER;
859 (*pwdMksys)=MKSYS_ITEMMONIKER;
861 return S_OK;
864 /*******************************************************************************
865 * ItemMonikerIROTData_QueryInterface
866 *******************************************************************************/
867 HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
870 ICOM_THIS_From_IROTData(IMoniker, iface);
872 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
874 return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);
877 /***********************************************************************
878 * ItemMonikerIROTData_AddRef
880 ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
882 ICOM_THIS_From_IROTData(IMoniker, iface);
884 TRACE("(%p)\n",iface);
886 return ItemMonikerImpl_AddRef(This);
889 /***********************************************************************
890 * ItemMonikerIROTData_Release
892 ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
894 ICOM_THIS_From_IROTData(IMoniker, iface);
896 TRACE("(%p)\n",iface);
898 return ItemMonikerImpl_Release(This);
901 /******************************************************************************
902 * ItemMonikerIROTData_GetComparaisonData
903 ******************************************************************************/
904 HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
905 BYTE* pbData,
906 ULONG cbMax,
907 ULONG* pcbData)
909 FIXME("(),stub!\n");
910 return E_NOTIMPL;
913 /******************************************************************************
914 * CreateItemMoniker16 [OLE2.28]
915 ******************************************************************************/
916 HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim,LPCOLESTR lpszItem,LPMONIKER* ppmk)
919 FIXME("(%s,%p),stub!\n",lpszDelim,ppmk);
920 *ppmk = NULL;
921 return E_NOTIMPL;
924 /******************************************************************************
925 * CreateItemMoniker [OLE.55]
926 ******************************************************************************/
927 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk)
929 ItemMonikerImpl* newItemMoniker = 0;
930 HRESULT hr = S_OK;
931 IID riid=IID_IMoniker;
933 TRACE("(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk);
935 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
937 if (newItemMoniker == 0)
938 return STG_E_INSUFFICIENTMEMORY;
940 hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
942 if (FAILED(hr)){
944 HeapFree(GetProcessHeap(),0,newItemMoniker);
945 return hr;
948 return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk);