enhmetafile added
[wine/multimedia.git] / ole / itemmoniker.c
blob8633d95db0dacd69b8e8acc17b60114dae6a666d
1 /***************************************************************************************
2 * ItemMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
7 #include <assert.h>
8 #include "winerror.h"
9 #include "debug.h"
10 #include "heap.h"
11 #include "winuser.h"
12 #include "file.h"
13 #include "winreg.h"
14 #include "objbase.h"
15 #include "wine/obj_inplace.h"
17 DEFAULT_DEBUG_CHANNEL(ole)
19 /* ItemMoniker data structure */
20 typedef struct ItemMonikerImpl{
22 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
24 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
25 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
27 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
29 ULONG ref; /* reference counter for this object */
31 LPOLESTR itemName; /* item name identified by this ItemMoniker */
33 LPOLESTR itemDelimiter; /* Delimiter string */
35 } ItemMonikerImpl;
37 /********************************************************************************/
38 /* ItemMoniker prototype functions : */
40 /* IUnknown prototype functions */
41 static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
42 static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface);
43 static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface);
45 /* IPersist prototype functions */
46 static HRESULT WINAPI ItemMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID);
48 /* IPersistStream prototype functions */
49 static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface);
50 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface, IStream* pStm);
51 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
52 static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
54 /* IMoniker prototype functions */
55 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
56 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
57 static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
58 static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
59 static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
60 static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
61 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
62 static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
63 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime);
64 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
65 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
66 static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
67 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
68 static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
69 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
71 /* Local function used by ItemMoniker implementation */
72 HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszPathName);
73 HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
75 /********************************************************************************/
76 /* IROTData prototype functions */
78 /* IUnknown prototype functions */
79 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
80 static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface);
81 static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface);
83 /* IROTData prototype function */
84 static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
86 /********************************************************************************/
87 /* Virtual function table for the ItemMonikerImpl class witch include Ipersist,*/
88 /* IPersistStream and IMoniker functions. */
89 static ICOM_VTABLE(IMoniker) VT_ItemMonikerImpl =
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 ItemMonikerROTDataImpl_QueryInterface,
121 ItemMonikerROTDataImpl_AddRef,
122 ItemMonikerROTDataImpl_Release,
123 ItemMonikerROTDataImpl_GetComparaisonData
126 /*******************************************************************************
127 * ItemMoniker_QueryInterface
128 *******************************************************************************/
129 HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
131 ICOM_THIS(ItemMonikerImpl,iface);
133 TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
135 /* Perform a sanity check on the parameters.*/
136 if ( (This==0) || (ppvObject==0) )
137 return E_INVALIDARG;
139 /* Initialize the return parameter */
140 *ppvObject = 0;
142 /* Compare the riid with the interface IDs implemented by this object.*/
143 if (IsEqualIID(&IID_IUnknown, riid) ||
144 IsEqualIID(&IID_IPersist, riid) ||
145 IsEqualIID(&IID_IPersistStream, riid) ||
146 IsEqualIID(&IID_IMoniker, riid)
148 *ppvObject = iface;
150 else if (IsEqualIID(&IID_IROTData, riid))
151 *ppvObject = (IROTData*)&(This->lpvtbl2);
153 /* Check that we obtained an interface.*/
154 if ((*ppvObject)==0)
155 return E_NOINTERFACE;
157 /* Query Interface always increases the reference count by one when it is successful */
158 ItemMonikerImpl_AddRef(iface);
160 return S_OK;
163 /******************************************************************************
164 * ItemMoniker_AddRef
165 ******************************************************************************/
166 ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
168 ICOM_THIS(ItemMonikerImpl,iface);
170 TRACE(ole,"(%p)\n",This);
172 return ++(This->ref);
175 /******************************************************************************
176 * ItemMoniker_Release
177 ******************************************************************************/
178 ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
180 ICOM_THIS(ItemMonikerImpl,iface);
182 TRACE(ole,"(%p)\n",This);
184 This->ref--;
186 /* destroy the object if there's no more reference on it */
187 if (This->ref==0){
189 ItemMonikerImpl_Destroy(This);
191 return 0;
193 return This->ref;;
196 /******************************************************************************
197 * ItemMoniker_GetClassID
198 ******************************************************************************/
199 HRESULT WINAPI ItemMonikerImpl_GetClassID(const IMoniker* iface,CLSID *pClassID)
201 TRACE(ole,"(%p,%p),stub!\n",iface,pClassID);
203 if (pClassID==NULL)
204 return E_POINTER;
206 *pClassID = CLSID_ItemMoniker;
208 return S_OK;
211 /******************************************************************************
212 * ItemMoniker_IsDirty
213 ******************************************************************************/
214 HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
216 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
217 method in the OLE-provided moniker interfaces always return S_FALSE because
218 their internal state never changes. */
220 TRACE(ole,"(%p)\n",iface);
222 return S_FALSE;
225 /******************************************************************************
226 * ItemMoniker_Load
227 ******************************************************************************/
228 HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
231 ICOM_THIS(ItemMonikerImpl,iface);
232 HRESULT res;
233 DWORD delimiterLength,nameLength;
234 CHAR *itemNameA,*itemDelimiterA;
235 ULONG bread;
237 /* for more details about data read by this function see coments of ItemMonikerImpl_Save function */
239 /* read item delimiter string length + 1 */
240 res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);
241 if (bread != sizeof(DWORD))
242 return E_FAIL;
244 /* read item delimiter string */
245 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
246 res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
247 if (bread != delimiterLength)
248 return E_FAIL;
250 This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,delimiterLength*sizeof(WCHAR));
251 if (!This->itemDelimiter)
252 return E_OUTOFMEMORY;
254 lstrcpyAtoW(This->itemDelimiter,itemDelimiterA);
256 /* read item name string length + 1*/
257 res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
258 if (bread != sizeof(DWORD))
259 return E_FAIL;
261 /* read item name string */
262 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
263 res=IStream_Read(pStm,itemNameA,nameLength,&bread);
264 if (bread != nameLength)
265 return E_FAIL;
267 This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,nameLength*sizeof(WCHAR));
268 if (!This->itemName)
269 return E_OUTOFMEMORY;
271 lstrcpyAtoW(This->itemName,itemNameA);
273 return res;
276 /******************************************************************************
277 * ItemMoniker_Save
278 ******************************************************************************/
279 HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,
280 IStream* pStm,/* pointer to the stream where the object is to be saved */
281 BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
283 ICOM_THIS(ItemMonikerImpl,iface);
284 HRESULT res;
285 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
286 DWORD nameLength=lstrlenW(This->itemName)+1;
287 CHAR *itemNameA,*itemDelimiterA;
289 /* data writen by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
290 /* 2) String (type A): item delimiter string ('\0' included) */
291 /* 3) DWORD : size of item name string ('\0' included) */
292 /* 4) String (type A): item name string ('\0' included) */
294 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
295 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
296 lstrcpyWtoA(itemNameA,This->itemName);
297 lstrcpyWtoA(itemDelimiterA,This->itemDelimiter);
299 res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
300 res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
301 res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
302 res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);
304 return res;
307 /******************************************************************************
308 * ItemMoniker_GetSizeMax
309 ******************************************************************************/
310 HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,
311 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
313 ICOM_THIS(ItemMonikerImpl,iface);
314 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
315 DWORD nameLength=lstrlenW(This->itemName)+1;
317 TRACE(ole,"(%p,%p)\n",iface,pcbSize);
319 if (pcbSize!=NULL)
320 return E_POINTER;
322 /* for more details see ItemMonikerImpl_Save coments */
324 pcbSize->LowPart = sizeof(DWORD) + /* DWORD witch contains delimiter length */
325 delimiterLength + /* item delimiter string */
326 sizeof(DWORD) + /* DWORD witch contains item name length */
327 nameLength + /* item name string */
328 34; /* this constant was added ! because when I tested this function it usually */
329 /* returns 34 bytes more than the number of bytes used by IMoniker::Save function */
330 pcbSize->HighPart=0;
332 return S_OK;
335 /******************************************************************************
336 * ItemMoniker_Construct (local function)
337 *******************************************************************************/
338 HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
341 int sizeStr1=lstrlenW(lpszItem);
342 int sizeStr2=lstrlenW(lpszDelim);
344 TRACE(ole,"(%p,%p)\n",This,lpszItem);
346 /* Initialize the virtual fgunction table. */
347 This->lpvtbl1 = &VT_ItemMonikerImpl;
348 This->lpvtbl2 = &VT_ROTDataImpl;
349 This->ref = 0;
351 This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
352 This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
354 if ((This->itemName==NULL)||(This->itemDelimiter==NULL))
355 return E_OUTOFMEMORY;
357 lstrcpyW(This->itemName,lpszItem);
358 lstrcpyW(This->itemDelimiter,lpszDelim);
360 return S_OK;
363 /******************************************************************************
364 * ItemMoniker_Destroy (local function)
365 *******************************************************************************/
366 HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
368 TRACE(ole,"(%p)\n",This);
370 if (This->itemName)
371 HeapFree(GetProcessHeap(),0,This->itemName);
373 if (This->itemDelimiter)
374 HeapFree(GetProcessHeap(),0,This->itemDelimiter);
376 HeapFree(GetProcessHeap(),0,This);
378 return S_OK;
381 /******************************************************************************
382 * ItemMoniker_BindToObject
383 ******************************************************************************/
384 HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
385 IBindCtx* pbc,
386 IMoniker* pmkToLeft,
387 REFIID riid,
388 VOID** ppvResult)
390 ICOM_THIS(ItemMonikerImpl,iface);
392 HRESULT res;
393 IID refid=IID_IOleItemContainer;
394 IOleItemContainer *poic=0;
396 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
398 if(ppvResult ==NULL)
399 return E_POINTER;
401 if(pmkToLeft==NULL)
402 return E_INVALIDARG;
404 *ppvResult=0;
406 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
408 if (SUCCEEDED(res)){
410 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);
412 IOleItemContainer_Release(poic);
415 return res;
418 /******************************************************************************
419 * ItemMoniker_BindToStorage
420 ******************************************************************************/
421 HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
422 IBindCtx* pbc,
423 IMoniker* pmkToLeft,
424 REFIID riid,
425 VOID** ppvResult)
427 ICOM_THIS(ItemMonikerImpl,iface);
429 HRESULT res;
430 IOleItemContainer *poic=0;
432 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
434 *ppvResult=0;
436 if(pmkToLeft==NULL)
437 return E_INVALIDARG;
439 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
441 if (SUCCEEDED(res)){
443 res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);
445 IOleItemContainer_Release(poic);
448 return res;
451 /******************************************************************************
452 * ItemMoniker_Reduce
453 ******************************************************************************/
454 HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
455 IBindCtx* pbc,
456 DWORD dwReduceHowFar,
457 IMoniker** ppmkToLeft,
458 IMoniker** ppmkReduced)
460 TRACE(ole,"(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
462 if (ppmkReduced==NULL)
463 return E_POINTER;
465 ItemMonikerImpl_AddRef(iface);
467 *ppmkReduced=iface;
469 return MK_S_REDUCED_TO_SELF;
471 /******************************************************************************
472 * ItemMoniker_ComposeWith
473 ******************************************************************************/
474 HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
475 IMoniker* pmkRight,
476 BOOL fOnlyIfNotGeneric,
477 IMoniker** ppmkComposite)
479 HRESULT res=S_OK;
480 DWORD mkSys,mkSys2;
481 IEnumMoniker* penumMk=0;
482 IMoniker *pmostLeftMk=0;
483 IMoniker* tempMkComposite=0;
485 TRACE(ole,"(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
487 if ((ppmkComposite==NULL)||(pmkRight==NULL))
488 return E_POINTER;
490 *ppmkComposite=0;
492 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
494 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
495 if(mkSys==MKSYS_ANTIMONIKER)
496 return res;
498 else
499 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
500 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
502 if(mkSys==MKSYS_GENERICCOMPOSITE){
504 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
506 if (FAILED(res))
507 return res;
509 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
511 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
513 if(mkSys2==MKSYS_ANTIMONIKER){
515 IMoniker_Release(pmostLeftMk);
517 tempMkComposite=iface;
518 IMoniker_AddRef(iface);
520 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
522 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
524 IMoniker_Release(tempMkComposite);
525 IMoniker_Release(pmostLeftMk);
527 tempMkComposite=*ppmkComposite;
528 IMoniker_AddRef(tempMkComposite);
530 return res;
532 else
533 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
535 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
536 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
537 a NULL moniker and a return value of MK_E_NEEDGENERIC */
538 else
539 if (!fOnlyIfNotGeneric)
540 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
542 else
543 return MK_E_NEEDGENERIC;
546 /******************************************************************************
547 * ItemMoniker_Enum
548 ******************************************************************************/
549 HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
551 TRACE(ole,"(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
553 if (ppenumMoniker == NULL)
554 return E_POINTER;
556 *ppenumMoniker = NULL;
558 return S_OK;
561 /******************************************************************************
562 * ItemMoniker_IsEqual
563 ******************************************************************************/
564 HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
567 CLSID clsid;
568 LPOLESTR dispName1,dispName2;
569 IBindCtx* bind;
570 HRESULT res;
572 TRACE(ole,"(%p,%p)\n",iface,pmkOtherMoniker);
574 if (pmkOtherMoniker==NULL)
575 return S_FALSE;
577 /* This method returns S_OK if both monikers are item monikers and their display names are */
578 /* identical (using a case-insensitive comparison); otherwise, the method returns S_FALSE. */
580 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
582 if (!IsEqualCLSID(&clsid,&CLSID_ItemMoniker))
583 return S_FALSE;
585 res=CreateBindCtx(0,&bind);
586 if (FAILED(res))
587 return res;
589 IMoniker_GetDisplayName(iface,bind,NULL,&dispName1);
590 IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2);
592 if (lstrcmpW(dispName1,dispName2)!=0)
593 return S_FALSE;
595 return S_OK;
598 /******************************************************************************
599 * ItemMoniker_Hash
600 ******************************************************************************/
601 HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
603 ICOM_THIS(ItemMonikerImpl,iface);
605 int h = 0,i,skip,len;
606 int off = 0;
607 LPOLESTR val;
609 if (pdwHash==NULL)
610 return E_POINTER;
612 val = This->itemName;
613 len = lstrlenW(val);
615 if (len < 16) {
616 for (i = len ; i > 0; i--) {
617 h = (h * 37) + val[off++];
619 } else {
620 /* only sample some characters */
621 skip = len / 8;
622 for (i = len ; i > 0; i -= skip, off += skip) {
623 h = (h * 39) + val[off];
627 *pdwHash=h;
629 return S_OK;
632 /******************************************************************************
633 * ItemMoniker_IsRunning
634 ******************************************************************************/
635 HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
636 IBindCtx* pbc,
637 IMoniker* pmkToLeft,
638 IMoniker* pmkNewlyRunning)
640 IRunningObjectTable* rot;
641 HRESULT res;
642 IOleItemContainer *poic=0;
643 ICOM_THIS(ItemMonikerImpl,iface);
645 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
647 /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
648 /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */
649 if (pmkToLeft==NULL)
650 if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
651 return S_OK;
652 else {
653 if (pbc==NULL)
654 return E_POINTER;
656 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
658 if (FAILED(res))
659 return res;
661 res = IRunningObjectTable_IsRunning(rot,iface);
663 IRunningObjectTable_Release(rot);
665 else{
667 /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */
668 /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
669 /* passing the string contained within this moniker. */
671 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
673 if (SUCCEEDED(res)){
675 res=IOleItemContainer_IsRunning(poic,This->itemName);
677 IOleItemContainer_Release(poic);
681 return res;
684 /******************************************************************************
685 * ItemMoniker_GetTimeOfLastChange
686 ******************************************************************************/
687 HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
688 IBindCtx* pbc,
689 IMoniker* pmkToLeft,
690 FILETIME* pItemTime)
692 IRunningObjectTable* rot;
693 HRESULT res;
694 IMoniker *compositeMk;
696 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
698 if (pItemTime==NULL)
699 return E_INVALIDARG;
701 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
702 if (pmkToLeft==NULL)
704 return MK_E_NOTBINDABLE;
705 else {
707 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
708 /* the time of last change. If the object is not in the ROT, the method calls */
709 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
711 res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
713 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
715 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
717 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
719 IMoniker_Release(compositeMk);
722 return res;
725 /******************************************************************************
726 * ItemMoniker_Inverse
727 ******************************************************************************/
728 HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
730 TRACE(ole,"(%p,%p)\n",iface,ppmk);
732 if (ppmk==NULL)
733 return E_POINTER;
735 return CreateAntiMoniker(ppmk);
738 /******************************************************************************
739 * ItemMoniker_CommonPrefixWith
740 ******************************************************************************/
741 HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
743 DWORD mkSys;
744 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
745 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
746 /* to this moniker and returns MK_S_US */
748 if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
750 *ppmkPrefix=iface;
752 IMoniker_AddRef(iface);
754 return MK_S_US;
756 else
757 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
758 /* the case where the other moniker is a generic composite. */
759 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
762 /******************************************************************************
763 * ItemMoniker_RelativePathTo
764 ******************************************************************************/
765 HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
767 TRACE(ole,"(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
769 if (ppmkRelPath==NULL)
770 return E_POINTER;
772 *ppmkRelPath=0;
774 return MK_E_NOTBINDABLE;
777 /******************************************************************************
778 * ItemMoniker_GetDisplayName
779 ******************************************************************************/
780 HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
781 IBindCtx* pbc,
782 IMoniker* pmkToLeft,
783 LPOLESTR *ppszDisplayName)
785 ICOM_THIS(ItemMonikerImpl,iface);
787 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
789 if (ppszDisplayName==NULL)
790 return E_POINTER;
792 if (pmkToLeft!=NULL){
793 return E_INVALIDARG;
796 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));
798 if (*ppszDisplayName==NULL)
799 return E_OUTOFMEMORY;
801 lstrcpyW(*ppszDisplayName,This->itemDelimiter);
802 lstrcatW(*ppszDisplayName,This->itemName);
804 return S_OK;
807 /******************************************************************************
808 * ItemMoniker_ParseDisplayName
809 ******************************************************************************/
810 HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
811 IBindCtx* pbc,
812 IMoniker* pmkToLeft,
813 LPOLESTR pszDisplayName,
814 ULONG* pchEaten,
815 IMoniker** ppmkOut)
817 IOleItemContainer* poic=0;
818 IParseDisplayName* ppdn=0;
819 LPOLESTR displayName;
820 HRESULT res;
821 ICOM_THIS(ItemMonikerImpl,iface);
823 /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
824 if (pmkToLeft==NULL)
826 return MK_E_SYNTAX;
828 else{
829 /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
830 /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */ /* name to IParseDisplayName::ParseDisplayName */
831 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
833 if (SUCCEEDED(res)){
835 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
837 res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);
839 res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);
841 IOleItemContainer_Release(poic);
842 IParseDisplayName_Release(ppdn);
845 return res;
848 /******************************************************************************
849 * ItemMoniker_IsSystemMonker
850 ******************************************************************************/
851 HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
853 TRACE(ole,"(%p,%p)\n",iface,pwdMksys);
855 if (!pwdMksys)
856 return E_POINTER;
858 (*pwdMksys)=MKSYS_ITEMMONIKER;
860 return S_OK;
863 /*******************************************************************************
864 * ItemMonikerIROTData_QueryInterface
865 *******************************************************************************/
866 HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
869 ICOM_THIS_From_IROTData(IMoniker, iface);
871 TRACE(ole,"(%p,%p,%p)\n",iface,riid,ppvObject);
873 return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);
876 /***********************************************************************
877 * ItemMonikerIROTData_AddRef
879 ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
881 ICOM_THIS_From_IROTData(IMoniker, iface);
883 TRACE(ole,"(%p)\n",iface);
885 return ItemMonikerImpl_AddRef(This);
888 /***********************************************************************
889 * ItemMonikerIROTData_Release
891 ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
893 ICOM_THIS_From_IROTData(IMoniker, iface);
895 TRACE(ole,"(%p)\n",iface);
897 return ItemMonikerImpl_Release(This);
900 /******************************************************************************
901 * ItemMonikerIROTData_GetComparaisonData
902 ******************************************************************************/
903 HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
904 BYTE* pbData,
905 ULONG cbMax,
906 ULONG* pcbData)
908 FIXME(ole,"(),stub!\n");
909 return E_NOTIMPL;
912 /******************************************************************************
913 * CreateItemMoniker16 [OLE2.28]
914 ******************************************************************************/
915 HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim,LPCOLESTR lpszItem,LPMONIKER* ppmk)
918 FIXME(ole,"(%s,%p),stub!\n",lpszDelim,ppmk);
919 *ppmk = NULL;
920 return E_NOTIMPL;
923 /******************************************************************************
924 * CreateItemMoniker [OLE.55]
925 ******************************************************************************/
926 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk)
928 ItemMonikerImpl* newItemMoniker = 0;
929 HRESULT hr = S_OK;
930 IID riid=IID_IMoniker;
932 TRACE(ole,"(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk);
934 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
936 if (newItemMoniker == 0)
937 return STG_E_INSUFFICIENTMEMORY;
939 hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
941 if (FAILED(hr)){
943 HeapFree(GetProcessHeap(),0,newItemMoniker);
944 return hr;
947 return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk);