2 * ItemMonikers implementation
4 * Copyright 1999 Noomen Hamza
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define NONAMELESSUNION
33 #include "wine/debug.h"
34 #include "wine/heap.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
40 /* ItemMoniker data structure */
41 typedef struct ItemMonikerImpl
{
42 IMoniker IMoniker_iface
; /* VTable relative to the IMoniker interface.*/
43 IROTData IROTData_iface
; /* VTable relative to the IROTData interface.*/
45 LPOLESTR itemName
; /* item name identified by this ItemMoniker */
46 LPOLESTR itemDelimiter
; /* Delimiter string */
47 IUnknown
*pMarshal
; /* custom marshaler */
50 static inline ItemMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
52 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IMoniker_iface
);
55 static ItemMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
);
57 static inline ItemMonikerImpl
*impl_from_IROTData(IROTData
*iface
)
59 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IROTData_iface
);
64 IUnknown IUnknown_iface
;
66 IOleItemContainer
*container
;
69 static struct container_lock
*impl_lock_from_IUnknown(IUnknown
*iface
)
71 return CONTAINING_RECORD(iface
, struct container_lock
, IUnknown_iface
);
74 static HRESULT WINAPI
container_lock_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
76 if (IsEqualIID(riid
, &IID_IUnknown
))
79 IUnknown_AddRef(iface
);
83 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
88 static ULONG WINAPI
container_lock_AddRef(IUnknown
*iface
)
90 struct container_lock
*lock
= impl_lock_from_IUnknown(iface
);
91 return InterlockedIncrement(&lock
->refcount
);
94 static ULONG WINAPI
container_lock_Release(IUnknown
*iface
)
96 struct container_lock
*lock
= impl_lock_from_IUnknown(iface
);
97 ULONG refcount
= InterlockedDecrement(&lock
->refcount
);
101 IOleItemContainer_LockContainer(lock
->container
, FALSE
);
102 IOleItemContainer_Release(lock
->container
);
109 static const IUnknownVtbl container_lock_vtbl
=
111 container_lock_QueryInterface
,
112 container_lock_AddRef
,
113 container_lock_Release
,
116 static HRESULT
set_container_lock(IOleItemContainer
*container
, IBindCtx
*pbc
)
118 struct container_lock
*lock
;
121 if (!(lock
= heap_alloc(sizeof(*lock
))))
122 return E_OUTOFMEMORY
;
124 if (FAILED(hr
= IOleItemContainer_LockContainer(container
, TRUE
)))
130 lock
->IUnknown_iface
.lpVtbl
= &container_lock_vtbl
;
132 lock
->container
= container
;
133 IOleItemContainer_AddRef(lock
->container
);
135 hr
= IBindCtx_RegisterObjectBound(pbc
, &lock
->IUnknown_iface
);
136 IUnknown_Release(&lock
->IUnknown_iface
);
140 /*******************************************************************************
141 * ItemMoniker_QueryInterface
142 *******************************************************************************/
143 static HRESULT WINAPI
ItemMonikerImpl_QueryInterface(IMoniker
*iface
, REFIID riid
, void **ppvObject
)
145 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
147 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppvObject
);
152 if (IsEqualIID(&IID_IUnknown
, riid
) ||
153 IsEqualIID(&IID_IPersist
, riid
) ||
154 IsEqualIID(&IID_IPersistStream
, riid
) ||
155 IsEqualIID(&IID_IMoniker
, riid
) ||
156 IsEqualGUID(&CLSID_ItemMoniker
, riid
))
160 else if (IsEqualIID(&IID_IROTData
, riid
))
161 *ppvObject
= &This
->IROTData_iface
;
162 else if (IsEqualIID(&IID_IMarshal
, riid
))
166 hr
= MonikerMarshal_Create(iface
, &This
->pMarshal
);
169 return IUnknown_QueryInterface(This
->pMarshal
, riid
, ppvObject
);
174 return E_NOINTERFACE
;
177 IMoniker_AddRef(iface
);
181 /******************************************************************************
183 ******************************************************************************/
184 static ULONG WINAPI
ItemMonikerImpl_AddRef(IMoniker
* iface
)
186 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
188 TRACE("(%p)\n",This
);
190 return InterlockedIncrement(&This
->ref
);
193 /******************************************************************************
194 * ItemMoniker_Release
195 ******************************************************************************/
196 static ULONG WINAPI
ItemMonikerImpl_Release(IMoniker
* iface
)
198 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
199 ULONG refcount
= InterlockedDecrement(&moniker
->ref
);
201 TRACE("%p, refcount %u.\n", iface
, refcount
);
205 if (moniker
->pMarshal
) IUnknown_Release(moniker
->pMarshal
);
206 heap_free(moniker
->itemName
);
207 heap_free(moniker
->itemDelimiter
);
214 /******************************************************************************
215 * ItemMoniker_GetClassID
216 ******************************************************************************/
217 static HRESULT WINAPI
ItemMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
219 TRACE("(%p,%p)\n",iface
,pClassID
);
224 *pClassID
= CLSID_ItemMoniker
;
229 /******************************************************************************
230 * ItemMoniker_IsDirty
231 ******************************************************************************/
232 static HRESULT WINAPI
ItemMonikerImpl_IsDirty(IMoniker
* iface
)
234 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
235 method in the OLE-provided moniker interfaces always return S_FALSE because
236 their internal state never changes. */
238 TRACE("(%p)\n",iface
);
243 static HRESULT
item_moniker_load_string_record(IStream
*stream
, WCHAR
**ret
)
245 DWORD str_len
, read_len
, lenW
, i
;
250 IStream_Read(stream
, &str_len
, sizeof(str_len
), &read_len
);
251 if (read_len
!= sizeof(str_len
))
261 if (!(buffer
= heap_alloc(str_len
)))
262 return E_OUTOFMEMORY
;
264 IStream_Read(stream
, buffer
, str_len
, &read_len
);
265 if (read_len
!= str_len
)
271 /* Skip ansi buffer, it must be null terminated. */
273 while (i
< str_len
&& buffer
[i
])
278 WARN("Expected null terminated ansi name.\n");
287 if (str_len
% sizeof(WCHAR
))
289 WARN("Unexpected Unicode name length %d.\n", str_len
);
294 str
= heap_alloc(str_len
+ sizeof(WCHAR
));
297 memcpy(str
, &buffer
[i
+ 1], str_len
);
298 str
[str_len
/ sizeof(WCHAR
)] = 0;
303 lenW
= MultiByteToWideChar(CP_ACP
, 0, buffer
, -1, NULL
, 0);
304 str
= heap_alloc(lenW
* sizeof(WCHAR
));
306 MultiByteToWideChar(CP_ACP
, 0, buffer
, -1, str
, lenW
);
323 /******************************************************************************
325 ******************************************************************************/
326 static HRESULT WINAPI
ItemMonikerImpl_Load(IMoniker
*iface
, IStream
*stream
)
328 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
331 TRACE("(%p, %p)\n", iface
, stream
);
333 /* Delimiter and name use the same record structure: 4 bytes byte-length field, followed by
334 string data. Data starts with single byte null-terminated string, WCHAR non-terminated
335 string optionally follows. Length of WCHAR string is determined as a difference between total
336 byte-length and single byte string length. */
338 hr
= item_moniker_load_string_record(stream
, &This
->itemDelimiter
);
340 hr
= item_moniker_load_string_record(stream
, &This
->itemName
);
345 /******************************************************************************
347 ******************************************************************************/
348 static HRESULT WINAPI
ItemMonikerImpl_Save(IMoniker
*iface
, IStream
*stream
, BOOL fClearDirty
)
350 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
355 TRACE("(%p, %p, %d)\n", iface
, stream
, fClearDirty
);
357 /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
358 /* 2) String (type A): item delimiter string ('\0' included) */
359 /* 3) DWORD : size of item name string ('\0' included) */
360 /* 4) String (type A): item name string ('\0' included) */
361 if (This
->itemDelimiter
)
363 str_len
= WideCharToMultiByte(CP_ACP
, 0, This
->itemDelimiter
, -1, NULL
, 0, NULL
, NULL
);
364 str
= heap_alloc(str_len
);
365 WideCharToMultiByte(CP_ACP
, 0, This
->itemDelimiter
, -1, str
, str_len
, NULL
, NULL
);
367 hr
= IStream_Write(stream
, &str_len
, sizeof(str_len
), NULL
);
368 hr
= IStream_Write(stream
, str
, str_len
, NULL
);
375 hr
= IStream_Write(stream
, &str_len
, sizeof(str_len
), NULL
);
378 str_len
= WideCharToMultiByte(CP_ACP
, 0, This
->itemName
, -1, NULL
, 0, NULL
, NULL
);
379 str
= heap_alloc(str_len
);
380 WideCharToMultiByte(CP_ACP
, 0, This
->itemName
, -1, str
, str_len
, NULL
, NULL
);
381 hr
= IStream_Write(stream
, &str_len
, sizeof(str_len
), NULL
);
382 hr
= IStream_Write(stream
, str
, str_len
, NULL
);
388 /******************************************************************************
389 * ItemMoniker_GetSizeMax
390 ******************************************************************************/
391 static HRESULT WINAPI
ItemMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
)
393 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
394 DWORD nameLength
=lstrlenW(This
->itemName
)+1;
396 TRACE("(%p,%p)\n",iface
,pcbSize
);
401 /* for more details see ItemMonikerImpl_Save comments */
403 pcbSize
->u
.LowPart
= sizeof(DWORD
) + /* DWORD which contains delimiter length */
404 sizeof(DWORD
) + /* DWORD which contains item name length */
405 nameLength
*4 + /* item name string */
406 18; /* strange, but true */
407 if (This
->itemDelimiter
)
408 pcbSize
->u
.LowPart
+= (lstrlenW(This
->itemDelimiter
) + 1) * 4;
410 pcbSize
->u
.HighPart
=0;
415 static DWORD
get_bind_speed_from_bindctx(IBindCtx
*pbc
)
417 DWORD bind_speed
= BINDSPEED_INDEFINITE
;
420 bind_opts
.cbStruct
= sizeof(bind_opts
);
421 if (SUCCEEDED(IBindCtx_GetBindOptions(pbc
, &bind_opts
)) && bind_opts
.dwTickCountDeadline
)
422 bind_speed
= bind_opts
.dwTickCountDeadline
< 2500 ? BINDSPEED_IMMEDIATE
: BINDSPEED_MODERATE
;
427 /******************************************************************************
428 * ItemMoniker_BindToObject
429 ******************************************************************************/
430 static HRESULT WINAPI
ItemMonikerImpl_BindToObject(IMoniker
* iface
,
436 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
437 IOleItemContainer
*container
;
440 TRACE("(%p,%p,%p,%s,%p)\n",iface
,pbc
,pmkToLeft
,debugstr_guid(riid
),ppvResult
);
450 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
453 if (FAILED(hr
= set_container_lock(container
, pbc
)))
454 WARN("Failed to lock container, hr %#x.\n", hr
);
456 hr
= IOleItemContainer_GetObject(container
, This
->itemName
, get_bind_speed_from_bindctx(pbc
), pbc
,
458 IOleItemContainer_Release(container
);
464 /******************************************************************************
465 * ItemMoniker_BindToStorage
466 ******************************************************************************/
467 static HRESULT WINAPI
ItemMonikerImpl_BindToStorage(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
, REFIID riid
,
470 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
471 IOleItemContainer
*container
;
474 TRACE("%p, %p, %p, %s, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_guid(riid
), ppvResult
);
481 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
484 if (FAILED(hr
= set_container_lock(container
, pbc
)))
485 WARN("Failed to lock container, hr %#x.\n", hr
);
487 hr
= IOleItemContainer_GetObjectStorage(container
, moniker
->itemName
, pbc
, riid
, ppvResult
);
488 IOleItemContainer_Release(container
);
494 /******************************************************************************
496 ******************************************************************************/
497 static HRESULT WINAPI
ItemMonikerImpl_Reduce(IMoniker
* iface
,
499 DWORD dwReduceHowFar
,
500 IMoniker
** ppmkToLeft
,
501 IMoniker
** ppmkReduced
)
503 TRACE("(%p,%p,%d,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
505 if (ppmkReduced
==NULL
)
508 ItemMonikerImpl_AddRef(iface
);
512 return MK_S_REDUCED_TO_SELF
;
514 /******************************************************************************
515 * ItemMoniker_ComposeWith
516 ******************************************************************************/
517 static HRESULT WINAPI
ItemMonikerImpl_ComposeWith(IMoniker
* iface
,
519 BOOL fOnlyIfNotGeneric
,
520 IMoniker
** ppmkComposite
)
523 DWORD mkSys
,mkSys2
, order
;
524 IEnumMoniker
* penumMk
=0;
525 IMoniker
*pmostLeftMk
=0;
526 IMoniker
* tempMkComposite
=0;
528 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
530 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
535 if (is_anti_moniker(pmkRight
, &order
))
537 return order
> 1 ? create_anti_moniker(order
- 1, ppmkComposite
) : S_OK
;
540 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
541 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
542 IMoniker_IsSystemMoniker(pmkRight
,&mkSys
);
543 if(mkSys
==MKSYS_GENERICCOMPOSITE
){
545 res
=IMoniker_Enum(pmkRight
,TRUE
,&penumMk
);
550 res
=IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
);
552 IMoniker_IsSystemMoniker(pmostLeftMk
,&mkSys2
);
554 if(mkSys2
==MKSYS_ANTIMONIKER
){
556 IMoniker_Release(pmostLeftMk
);
558 tempMkComposite
=iface
;
559 IMoniker_AddRef(iface
);
561 while(IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
)==S_OK
){
563 res
=CreateGenericComposite(tempMkComposite
,pmostLeftMk
,ppmkComposite
);
565 IMoniker_Release(tempMkComposite
);
566 IMoniker_Release(pmostLeftMk
);
568 tempMkComposite
=*ppmkComposite
;
569 IMoniker_AddRef(tempMkComposite
);
574 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
576 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
577 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
578 a NULL moniker and a return value of MK_E_NEEDGENERIC */
580 if (!fOnlyIfNotGeneric
)
581 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
584 return MK_E_NEEDGENERIC
;
587 /******************************************************************************
589 ******************************************************************************/
590 static HRESULT WINAPI
ItemMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
592 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
594 if (ppenumMoniker
== NULL
)
597 *ppenumMoniker
= NULL
;
602 /******************************************************************************
603 * ItemMoniker_IsEqual
604 ******************************************************************************/
605 static HRESULT WINAPI
ItemMonikerImpl_IsEqual(IMoniker
*iface
, IMoniker
*other
)
607 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
609 TRACE("%p, %p.\n", iface
, other
);
614 other_moniker
= unsafe_impl_from_IMoniker(other
);
618 return !wcsicmp(moniker
->itemName
, other_moniker
->itemName
) ? S_OK
: S_FALSE
;
621 /******************************************************************************
623 ******************************************************************************/
624 static HRESULT WINAPI
ItemMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
626 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
635 val
= This
->itemName
;
638 for (i
= len
; i
> 0; i
--)
639 h
= (h
* 3) ^ towupper(val
[off
++]);
646 /******************************************************************************
647 * ItemMoniker_IsRunning
648 ******************************************************************************/
649 static HRESULT WINAPI
ItemMonikerImpl_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
,
650 IMoniker
*pmkNewlyRunning
)
652 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
653 IOleItemContainer
*container
;
654 IRunningObjectTable
* rot
;
657 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
666 return IMoniker_IsEqual(iface
, pmkNewlyRunning
);
670 hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
);
673 hr
= IRunningObjectTable_IsRunning(rot
, iface
);
674 IRunningObjectTable_Release(rot
);
680 /* Container itself must be running too. */
681 hr
= IMoniker_IsRunning(pmkToLeft
, pbc
, NULL
, NULL
);
685 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
688 hr
= IOleItemContainer_IsRunning(container
, moniker
->itemName
);
689 IOleItemContainer_Release(container
);
696 /******************************************************************************
697 * ItemMoniker_GetTimeOfLastChange
698 ******************************************************************************/
699 static HRESULT WINAPI
ItemMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
704 IRunningObjectTable
* rot
;
706 IMoniker
*compositeMk
;
708 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pItemTime
);
713 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
716 return MK_E_NOTBINDABLE
;
719 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
720 /* the time of last change. If the object is not in the ROT, the method calls */
721 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
723 res
=CreateGenericComposite(pmkToLeft
,iface
,&compositeMk
);
727 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
729 IMoniker_Release(compositeMk
);
733 if (IRunningObjectTable_GetTimeOfLastChange(rot
,compositeMk
,pItemTime
)!=S_OK
)
735 res
=IMoniker_GetTimeOfLastChange(pmkToLeft
,pbc
,NULL
,pItemTime
);
737 IMoniker_Release(compositeMk
);
743 /******************************************************************************
744 * ItemMoniker_Inverse
745 ******************************************************************************/
746 static HRESULT WINAPI
ItemMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
748 TRACE("(%p,%p)\n",iface
,ppmk
);
753 return CreateAntiMoniker(ppmk
);
756 /******************************************************************************
757 * ItemMoniker_CommonPrefixWith
758 ******************************************************************************/
759 static HRESULT WINAPI
ItemMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
763 TRACE("(%p,%p)\n", pmkOther
, ppmkPrefix
);
765 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
766 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
767 /* to this moniker and returns MK_S_US */
769 if((mkSys
==MKSYS_ITEMMONIKER
) && (IMoniker_IsEqual(iface
,pmkOther
)==S_OK
) ){
773 IMoniker_AddRef(iface
);
778 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
779 /* the case where the other moniker is a generic composite. */
780 return MonikerCommonPrefixWith(iface
,pmkOther
,ppmkPrefix
);
783 /******************************************************************************
784 * ItemMoniker_RelativePathTo
785 ******************************************************************************/
786 static HRESULT WINAPI
ItemMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
)
788 TRACE("(%p,%p,%p)\n",iface
,pmOther
,ppmkRelPath
);
790 if (ppmkRelPath
==NULL
)
795 return MK_E_NOTBINDABLE
;
798 /******************************************************************************
799 * ItemMoniker_GetDisplayName
800 ******************************************************************************/
801 static HRESULT WINAPI
ItemMonikerImpl_GetDisplayName(IMoniker
* iface
,
804 LPOLESTR
*ppszDisplayName
)
806 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
809 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
811 if (ppszDisplayName
==NULL
)
814 if (pmkToLeft
!=NULL
){
818 size
= lstrlenW(This
->itemName
) + 1;
819 if (This
->itemDelimiter
)
820 size
+= lstrlenW(This
->itemDelimiter
);
821 size
*= sizeof(WCHAR
);
823 *ppszDisplayName
= CoTaskMemAlloc(size
);
824 if (*ppszDisplayName
==NULL
)
825 return E_OUTOFMEMORY
;
827 (*ppszDisplayName
)[0] = 0;
828 if (This
->itemDelimiter
)
829 lstrcatW(*ppszDisplayName
, This
->itemDelimiter
);
830 lstrcatW(*ppszDisplayName
,This
->itemName
);
832 TRACE("-- %s\n", debugstr_w(*ppszDisplayName
));
837 /******************************************************************************
838 * ItemMoniker_ParseDisplayName
839 ******************************************************************************/
840 static HRESULT WINAPI
ItemMonikerImpl_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
,
841 LPOLESTR displayname
, ULONG
*eaten
, IMoniker
**ppmkOut
)
843 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
844 IOleItemContainer
*container
;
845 IParseDisplayName
*parser
;
848 TRACE("%p, %p, %p, %s, %p, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_w(displayname
), eaten
, ppmkOut
);
853 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
856 if (SUCCEEDED(hr
= set_container_lock(container
, pbc
)))
858 hr
= IOleItemContainer_GetObject(container
, This
->itemName
, get_bind_speed_from_bindctx(pbc
), pbc
,
859 &IID_IParseDisplayName
, (void **)&parser
);
862 hr
= IParseDisplayName_ParseDisplayName(parser
, pbc
, displayname
, eaten
, ppmkOut
);
863 IParseDisplayName_Release(parser
);
866 IOleItemContainer_Release(container
);
872 /******************************************************************************
873 * ItemMoniker_IsSystemMoniker
874 ******************************************************************************/
875 static HRESULT WINAPI
ItemMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
877 TRACE("(%p,%p)\n",iface
,pwdMksys
);
882 (*pwdMksys
)=MKSYS_ITEMMONIKER
;
887 /*******************************************************************************
888 * ItemMonikerIROTData_QueryInterface
889 *******************************************************************************/
890 static HRESULT WINAPI
ItemMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
894 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
896 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppvObject
);
898 return ItemMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
901 /***********************************************************************
902 * ItemMonikerIROTData_AddRef
904 static ULONG WINAPI
ItemMonikerROTDataImpl_AddRef(IROTData
*iface
)
906 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
908 TRACE("(%p)\n",iface
);
910 return ItemMonikerImpl_AddRef(&This
->IMoniker_iface
);
913 /***********************************************************************
914 * ItemMonikerIROTData_Release
916 static ULONG WINAPI
ItemMonikerROTDataImpl_Release(IROTData
* iface
)
918 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
920 TRACE("(%p)\n",iface
);
922 return ItemMonikerImpl_Release(&This
->IMoniker_iface
);
925 /******************************************************************************
926 * ItemMonikerIROTData_GetComparisonData
927 ******************************************************************************/
928 static HRESULT WINAPI
ItemMonikerROTDataImpl_GetComparisonData(IROTData
*iface
, BYTE
*buffer
, ULONG max_len
,
931 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
932 int name_len
= lstrlenW(This
->itemName
);
936 TRACE("(%p, %p, %u, %p)\n", iface
, buffer
, max_len
, data_len
);
938 delim_len
= This
->itemDelimiter
&& This
->itemDelimiter
[0] ? lstrlenW(This
->itemDelimiter
) : 0;
939 *data_len
= sizeof(CLSID
) + sizeof(WCHAR
) + (delim_len
+ name_len
) * sizeof(WCHAR
);
940 if (max_len
< *data_len
)
941 return E_OUTOFMEMORY
;
944 memcpy(buffer
, &CLSID_ItemMoniker
, sizeof(CLSID
));
945 buffer
+= sizeof(CLSID
);
947 /* write delimiter */
948 for (i
= 0, ptrW
= (WCHAR
*)buffer
; i
< delim_len
; ++i
)
949 ptrW
[i
] = towupper(This
->itemDelimiter
[i
]);
950 buffer
+= (delim_len
* sizeof(WCHAR
));
953 for (i
= 0, ptrW
= (WCHAR
*)buffer
; i
< name_len
; ++i
)
954 ptrW
[i
] = towupper(This
->itemName
[i
]);
960 /********************************************************************************/
961 /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/
962 /* IPersistStream and IMoniker functions. */
963 static const IMonikerVtbl VT_ItemMonikerImpl
=
965 ItemMonikerImpl_QueryInterface
,
966 ItemMonikerImpl_AddRef
,
967 ItemMonikerImpl_Release
,
968 ItemMonikerImpl_GetClassID
,
969 ItemMonikerImpl_IsDirty
,
970 ItemMonikerImpl_Load
,
971 ItemMonikerImpl_Save
,
972 ItemMonikerImpl_GetSizeMax
,
973 ItemMonikerImpl_BindToObject
,
974 ItemMonikerImpl_BindToStorage
,
975 ItemMonikerImpl_Reduce
,
976 ItemMonikerImpl_ComposeWith
,
977 ItemMonikerImpl_Enum
,
978 ItemMonikerImpl_IsEqual
,
979 ItemMonikerImpl_Hash
,
980 ItemMonikerImpl_IsRunning
,
981 ItemMonikerImpl_GetTimeOfLastChange
,
982 ItemMonikerImpl_Inverse
,
983 ItemMonikerImpl_CommonPrefixWith
,
984 ItemMonikerImpl_RelativePathTo
,
985 ItemMonikerImpl_GetDisplayName
,
986 ItemMonikerImpl_ParseDisplayName
,
987 ItemMonikerImpl_IsSystemMoniker
990 static ItemMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
)
992 if (iface
->lpVtbl
!= &VT_ItemMonikerImpl
)
994 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IMoniker_iface
);
997 /********************************************************************************/
998 /* Virtual function table for the IROTData class. */
999 static const IROTDataVtbl VT_ROTDataImpl
=
1001 ItemMonikerROTDataImpl_QueryInterface
,
1002 ItemMonikerROTDataImpl_AddRef
,
1003 ItemMonikerROTDataImpl_Release
,
1004 ItemMonikerROTDataImpl_GetComparisonData
1007 /******************************************************************************
1008 * CreateItemMoniker [OLE32.@]
1009 ******************************************************************************/
1010 HRESULT WINAPI
CreateItemMoniker(const WCHAR
*delimiter
, const WCHAR
*name
, IMoniker
**ret
)
1012 ItemMonikerImpl
*moniker
;
1016 TRACE("%s, %s, %p.\n", debugstr_w(delimiter
), debugstr_w(name
), ret
);
1018 if (!(moniker
= heap_alloc_zero(sizeof(*moniker
))))
1019 return E_OUTOFMEMORY
;
1021 moniker
->IMoniker_iface
.lpVtbl
= &VT_ItemMonikerImpl
;
1022 moniker
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
1025 str_len
= (lstrlenW(name
) + 1) * sizeof(WCHAR
);
1026 moniker
->itemName
= heap_alloc(str_len
);
1027 if (!moniker
->itemName
)
1032 memcpy(moniker
->itemName
, name
, str_len
);
1036 str_len
= (lstrlenW(delimiter
) + 1) * sizeof(WCHAR
);
1037 moniker
->itemDelimiter
= heap_alloc(str_len
);
1038 if (!moniker
->itemDelimiter
)
1043 memcpy(moniker
->itemDelimiter
, delimiter
, str_len
);
1046 *ret
= &moniker
->IMoniker_iface
;
1051 IMoniker_Release(&moniker
->IMoniker_iface
);
1056 HRESULT WINAPI
ItemMoniker_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
1061 TRACE("(%p, %s, %p)\n", outer
, debugstr_guid(riid
), ppv
);
1066 return CLASS_E_NOAGGREGATION
;
1068 if (FAILED(hr
= CreateItemMoniker(L
"", L
"", &moniker
)))
1071 hr
= IMoniker_QueryInterface(moniker
, riid
, ppv
);
1072 IMoniker_Release(moniker
);