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
;
515 static HRESULT WINAPI
ItemMonikerImpl_ComposeWith(IMoniker
*iface
, IMoniker
*right
,
516 BOOL only_if_not_generic
, IMoniker
**result
)
520 TRACE("%p, %p, %d, %p\n", iface
, right
, only_if_not_generic
, result
);
522 if (!result
|| !right
)
527 if (is_anti_moniker(right
, &order
))
528 return order
> 1 ? create_anti_moniker(order
- 1, result
) : S_OK
;
530 return only_if_not_generic
? MK_E_NEEDGENERIC
: CreateGenericComposite(iface
, right
, result
);
533 /******************************************************************************
535 ******************************************************************************/
536 static HRESULT WINAPI
ItemMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
538 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
540 if (ppenumMoniker
== NULL
)
543 *ppenumMoniker
= NULL
;
548 /******************************************************************************
549 * ItemMoniker_IsEqual
550 ******************************************************************************/
551 static HRESULT WINAPI
ItemMonikerImpl_IsEqual(IMoniker
*iface
, IMoniker
*other
)
553 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
555 TRACE("%p, %p.\n", iface
, other
);
560 other_moniker
= unsafe_impl_from_IMoniker(other
);
564 return !wcsicmp(moniker
->itemName
, other_moniker
->itemName
) ? S_OK
: S_FALSE
;
567 /******************************************************************************
569 ******************************************************************************/
570 static HRESULT WINAPI
ItemMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
572 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
581 val
= This
->itemName
;
584 for (i
= len
; i
> 0; i
--)
585 h
= (h
* 3) ^ towupper(val
[off
++]);
592 /******************************************************************************
593 * ItemMoniker_IsRunning
594 ******************************************************************************/
595 static HRESULT WINAPI
ItemMonikerImpl_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
,
596 IMoniker
*pmkNewlyRunning
)
598 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
599 IOleItemContainer
*container
;
600 IRunningObjectTable
* rot
;
603 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
612 return IMoniker_IsEqual(iface
, pmkNewlyRunning
);
616 hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
);
619 hr
= IRunningObjectTable_IsRunning(rot
, iface
);
620 IRunningObjectTable_Release(rot
);
626 /* Container itself must be running too. */
627 hr
= IMoniker_IsRunning(pmkToLeft
, pbc
, NULL
, NULL
);
631 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
634 hr
= IOleItemContainer_IsRunning(container
, moniker
->itemName
);
635 IOleItemContainer_Release(container
);
642 /******************************************************************************
643 * ItemMoniker_GetTimeOfLastChange
644 ******************************************************************************/
645 static HRESULT WINAPI
ItemMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
650 IRunningObjectTable
* rot
;
652 IMoniker
*compositeMk
;
654 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pItemTime
);
659 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
662 return MK_E_NOTBINDABLE
;
665 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
666 /* the time of last change. If the object is not in the ROT, the method calls */
667 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
669 res
=CreateGenericComposite(pmkToLeft
,iface
,&compositeMk
);
673 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
675 IMoniker_Release(compositeMk
);
679 if (IRunningObjectTable_GetTimeOfLastChange(rot
,compositeMk
,pItemTime
)!=S_OK
)
681 res
=IMoniker_GetTimeOfLastChange(pmkToLeft
,pbc
,NULL
,pItemTime
);
683 IMoniker_Release(compositeMk
);
689 /******************************************************************************
690 * ItemMoniker_Inverse
691 ******************************************************************************/
692 static HRESULT WINAPI
ItemMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
694 TRACE("(%p,%p)\n",iface
,ppmk
);
699 return CreateAntiMoniker(ppmk
);
702 static HRESULT WINAPI
ItemMonikerImpl_CommonPrefixWith(IMoniker
*iface
, IMoniker
*other
,
705 TRACE("%p, %p, %p\n", iface
, other
, prefix
);
707 if (IMoniker_IsEqual(iface
, other
) == S_OK
)
710 IMoniker_AddRef(iface
);
714 return MonikerCommonPrefixWith(iface
, other
, prefix
);
717 static HRESULT WINAPI
ItemMonikerImpl_RelativePathTo(IMoniker
*iface
, IMoniker
*other
, IMoniker
**result
)
719 TRACE("%p, %p, %p.\n", iface
, other
, result
);
721 if (!other
|| !result
)
726 return MK_E_NOTBINDABLE
;
729 /******************************************************************************
730 * ItemMoniker_GetDisplayName
731 ******************************************************************************/
732 static HRESULT WINAPI
ItemMonikerImpl_GetDisplayName(IMoniker
* iface
,
735 LPOLESTR
*ppszDisplayName
)
737 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
740 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
742 if (ppszDisplayName
==NULL
)
745 if (pmkToLeft
!=NULL
){
749 size
= lstrlenW(This
->itemName
) + 1;
750 if (This
->itemDelimiter
)
751 size
+= lstrlenW(This
->itemDelimiter
);
752 size
*= sizeof(WCHAR
);
754 *ppszDisplayName
= CoTaskMemAlloc(size
);
755 if (*ppszDisplayName
==NULL
)
756 return E_OUTOFMEMORY
;
758 (*ppszDisplayName
)[0] = 0;
759 if (This
->itemDelimiter
)
760 lstrcatW(*ppszDisplayName
, This
->itemDelimiter
);
761 lstrcatW(*ppszDisplayName
,This
->itemName
);
763 TRACE("-- %s\n", debugstr_w(*ppszDisplayName
));
768 /******************************************************************************
769 * ItemMoniker_ParseDisplayName
770 ******************************************************************************/
771 static HRESULT WINAPI
ItemMonikerImpl_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
,
772 LPOLESTR displayname
, ULONG
*eaten
, IMoniker
**ppmkOut
)
774 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
775 IOleItemContainer
*container
;
776 IParseDisplayName
*parser
;
779 TRACE("%p, %p, %p, %s, %p, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_w(displayname
), eaten
, ppmkOut
);
784 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
787 if (SUCCEEDED(hr
= set_container_lock(container
, pbc
)))
789 hr
= IOleItemContainer_GetObject(container
, This
->itemName
, get_bind_speed_from_bindctx(pbc
), pbc
,
790 &IID_IParseDisplayName
, (void **)&parser
);
793 hr
= IParseDisplayName_ParseDisplayName(parser
, pbc
, displayname
, eaten
, ppmkOut
);
794 IParseDisplayName_Release(parser
);
797 IOleItemContainer_Release(container
);
803 /******************************************************************************
804 * ItemMoniker_IsSystemMoniker
805 ******************************************************************************/
806 static HRESULT WINAPI
ItemMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
808 TRACE("(%p,%p)\n",iface
,pwdMksys
);
813 (*pwdMksys
)=MKSYS_ITEMMONIKER
;
818 /*******************************************************************************
819 * ItemMonikerIROTData_QueryInterface
820 *******************************************************************************/
821 static HRESULT WINAPI
ItemMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
825 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
827 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppvObject
);
829 return ItemMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
832 /***********************************************************************
833 * ItemMonikerIROTData_AddRef
835 static ULONG WINAPI
ItemMonikerROTDataImpl_AddRef(IROTData
*iface
)
837 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
839 TRACE("(%p)\n",iface
);
841 return ItemMonikerImpl_AddRef(&This
->IMoniker_iface
);
844 /***********************************************************************
845 * ItemMonikerIROTData_Release
847 static ULONG WINAPI
ItemMonikerROTDataImpl_Release(IROTData
* iface
)
849 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
851 TRACE("(%p)\n",iface
);
853 return ItemMonikerImpl_Release(&This
->IMoniker_iface
);
856 /******************************************************************************
857 * ItemMonikerIROTData_GetComparisonData
858 ******************************************************************************/
859 static HRESULT WINAPI
ItemMonikerROTDataImpl_GetComparisonData(IROTData
*iface
, BYTE
*buffer
, ULONG max_len
,
862 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
863 int name_len
= lstrlenW(This
->itemName
);
867 TRACE("(%p, %p, %u, %p)\n", iface
, buffer
, max_len
, data_len
);
869 delim_len
= This
->itemDelimiter
&& This
->itemDelimiter
[0] ? lstrlenW(This
->itemDelimiter
) : 0;
870 *data_len
= sizeof(CLSID
) + sizeof(WCHAR
) + (delim_len
+ name_len
) * sizeof(WCHAR
);
871 if (max_len
< *data_len
)
872 return E_OUTOFMEMORY
;
875 memcpy(buffer
, &CLSID_ItemMoniker
, sizeof(CLSID
));
876 buffer
+= sizeof(CLSID
);
878 /* write delimiter */
879 for (i
= 0, ptrW
= (WCHAR
*)buffer
; i
< delim_len
; ++i
)
880 ptrW
[i
] = towupper(This
->itemDelimiter
[i
]);
881 buffer
+= (delim_len
* sizeof(WCHAR
));
884 for (i
= 0, ptrW
= (WCHAR
*)buffer
; i
< name_len
; ++i
)
885 ptrW
[i
] = towupper(This
->itemName
[i
]);
891 /********************************************************************************/
892 /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/
893 /* IPersistStream and IMoniker functions. */
894 static const IMonikerVtbl VT_ItemMonikerImpl
=
896 ItemMonikerImpl_QueryInterface
,
897 ItemMonikerImpl_AddRef
,
898 ItemMonikerImpl_Release
,
899 ItemMonikerImpl_GetClassID
,
900 ItemMonikerImpl_IsDirty
,
901 ItemMonikerImpl_Load
,
902 ItemMonikerImpl_Save
,
903 ItemMonikerImpl_GetSizeMax
,
904 ItemMonikerImpl_BindToObject
,
905 ItemMonikerImpl_BindToStorage
,
906 ItemMonikerImpl_Reduce
,
907 ItemMonikerImpl_ComposeWith
,
908 ItemMonikerImpl_Enum
,
909 ItemMonikerImpl_IsEqual
,
910 ItemMonikerImpl_Hash
,
911 ItemMonikerImpl_IsRunning
,
912 ItemMonikerImpl_GetTimeOfLastChange
,
913 ItemMonikerImpl_Inverse
,
914 ItemMonikerImpl_CommonPrefixWith
,
915 ItemMonikerImpl_RelativePathTo
,
916 ItemMonikerImpl_GetDisplayName
,
917 ItemMonikerImpl_ParseDisplayName
,
918 ItemMonikerImpl_IsSystemMoniker
921 static ItemMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
)
923 if (iface
->lpVtbl
!= &VT_ItemMonikerImpl
)
925 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IMoniker_iface
);
928 /********************************************************************************/
929 /* Virtual function table for the IROTData class. */
930 static const IROTDataVtbl VT_ROTDataImpl
=
932 ItemMonikerROTDataImpl_QueryInterface
,
933 ItemMonikerROTDataImpl_AddRef
,
934 ItemMonikerROTDataImpl_Release
,
935 ItemMonikerROTDataImpl_GetComparisonData
938 /******************************************************************************
939 * CreateItemMoniker [OLE32.@]
940 ******************************************************************************/
941 HRESULT WINAPI
CreateItemMoniker(const WCHAR
*delimiter
, const WCHAR
*name
, IMoniker
**ret
)
943 ItemMonikerImpl
*moniker
;
947 TRACE("%s, %s, %p.\n", debugstr_w(delimiter
), debugstr_w(name
), ret
);
949 if (!(moniker
= heap_alloc_zero(sizeof(*moniker
))))
950 return E_OUTOFMEMORY
;
952 moniker
->IMoniker_iface
.lpVtbl
= &VT_ItemMonikerImpl
;
953 moniker
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
956 str_len
= (lstrlenW(name
) + 1) * sizeof(WCHAR
);
957 moniker
->itemName
= heap_alloc(str_len
);
958 if (!moniker
->itemName
)
963 memcpy(moniker
->itemName
, name
, str_len
);
967 str_len
= (lstrlenW(delimiter
) + 1) * sizeof(WCHAR
);
968 moniker
->itemDelimiter
= heap_alloc(str_len
);
969 if (!moniker
->itemDelimiter
)
974 memcpy(moniker
->itemDelimiter
, delimiter
, str_len
);
977 *ret
= &moniker
->IMoniker_iface
;
982 IMoniker_Release(&moniker
->IMoniker_iface
);
987 HRESULT WINAPI
ItemMoniker_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
992 TRACE("(%p, %s, %p)\n", outer
, debugstr_guid(riid
), ppv
);
997 return CLASS_E_NOAGGREGATION
;
999 if (FAILED(hr
= CreateItemMoniker(L
"", L
"", &moniker
)))
1002 hr
= IMoniker_QueryInterface(moniker
, riid
, ppv
);
1003 IMoniker_Release(moniker
);