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"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
39 /* ItemMoniker data structure */
40 typedef struct ItemMonikerImpl
{
41 IMoniker IMoniker_iface
; /* VTable relative to the IMoniker interface.*/
42 IROTData IROTData_iface
; /* VTable relative to the IROTData interface.*/
44 LPOLESTR itemName
; /* item name identified by this ItemMoniker */
45 LPOLESTR itemDelimiter
; /* Delimiter string */
46 IUnknown
*pMarshal
; /* custom marshaler */
49 static inline ItemMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
51 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IMoniker_iface
);
54 static ItemMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
);
56 static inline ItemMonikerImpl
*impl_from_IROTData(IROTData
*iface
)
58 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IROTData_iface
);
63 IUnknown IUnknown_iface
;
65 IOleItemContainer
*container
;
68 static struct container_lock
*impl_lock_from_IUnknown(IUnknown
*iface
)
70 return CONTAINING_RECORD(iface
, struct container_lock
, IUnknown_iface
);
73 static HRESULT WINAPI
container_lock_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
75 if (IsEqualIID(riid
, &IID_IUnknown
))
78 IUnknown_AddRef(iface
);
82 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
87 static ULONG WINAPI
container_lock_AddRef(IUnknown
*iface
)
89 struct container_lock
*lock
= impl_lock_from_IUnknown(iface
);
90 return InterlockedIncrement(&lock
->refcount
);
93 static ULONG WINAPI
container_lock_Release(IUnknown
*iface
)
95 struct container_lock
*lock
= impl_lock_from_IUnknown(iface
);
96 ULONG refcount
= InterlockedDecrement(&lock
->refcount
);
100 IOleItemContainer_LockContainer(lock
->container
, FALSE
);
101 IOleItemContainer_Release(lock
->container
);
108 static const IUnknownVtbl container_lock_vtbl
=
110 container_lock_QueryInterface
,
111 container_lock_AddRef
,
112 container_lock_Release
,
115 static HRESULT
set_container_lock(IOleItemContainer
*container
, IBindCtx
*pbc
)
117 struct container_lock
*lock
;
120 if (!(lock
= malloc(sizeof(*lock
))))
121 return E_OUTOFMEMORY
;
123 if (FAILED(hr
= IOleItemContainer_LockContainer(container
, TRUE
)))
129 lock
->IUnknown_iface
.lpVtbl
= &container_lock_vtbl
;
131 lock
->container
= container
;
132 IOleItemContainer_AddRef(lock
->container
);
134 hr
= IBindCtx_RegisterObjectBound(pbc
, &lock
->IUnknown_iface
);
135 IUnknown_Release(&lock
->IUnknown_iface
);
139 /*******************************************************************************
140 * ItemMoniker_QueryInterface
141 *******************************************************************************/
142 static HRESULT WINAPI
ItemMonikerImpl_QueryInterface(IMoniker
*iface
, REFIID riid
, void **ppvObject
)
144 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
146 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppvObject
);
151 if (IsEqualIID(&IID_IUnknown
, riid
) ||
152 IsEqualIID(&IID_IPersist
, riid
) ||
153 IsEqualIID(&IID_IPersistStream
, riid
) ||
154 IsEqualIID(&IID_IMoniker
, riid
) ||
155 IsEqualGUID(&CLSID_ItemMoniker
, riid
))
159 else if (IsEqualIID(&IID_IROTData
, riid
))
160 *ppvObject
= &This
->IROTData_iface
;
161 else if (IsEqualIID(&IID_IMarshal
, riid
))
165 hr
= MonikerMarshal_Create(iface
, &This
->pMarshal
);
168 return IUnknown_QueryInterface(This
->pMarshal
, riid
, ppvObject
);
173 return E_NOINTERFACE
;
176 IMoniker_AddRef(iface
);
180 /******************************************************************************
182 ******************************************************************************/
183 static ULONG WINAPI
ItemMonikerImpl_AddRef(IMoniker
* iface
)
185 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
187 TRACE("(%p)\n",This
);
189 return InterlockedIncrement(&This
->ref
);
192 /******************************************************************************
193 * ItemMoniker_Release
194 ******************************************************************************/
195 static ULONG WINAPI
ItemMonikerImpl_Release(IMoniker
* iface
)
197 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
198 ULONG refcount
= InterlockedDecrement(&moniker
->ref
);
200 TRACE("%p, refcount %lu.\n", iface
, refcount
);
204 if (moniker
->pMarshal
) IUnknown_Release(moniker
->pMarshal
);
205 free(moniker
->itemName
);
206 free(moniker
->itemDelimiter
);
213 /******************************************************************************
214 * ItemMoniker_GetClassID
215 ******************************************************************************/
216 static HRESULT WINAPI
ItemMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
218 TRACE("(%p,%p)\n",iface
,pClassID
);
223 *pClassID
= CLSID_ItemMoniker
;
228 /******************************************************************************
229 * ItemMoniker_IsDirty
230 ******************************************************************************/
231 static HRESULT WINAPI
ItemMonikerImpl_IsDirty(IMoniker
* iface
)
233 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
234 method in the OLE-provided moniker interfaces always return S_FALSE because
235 their internal state never changes. */
237 TRACE("(%p)\n",iface
);
242 static HRESULT
item_moniker_load_string_record(IStream
*stream
, WCHAR
**ret
)
244 DWORD str_len
, read_len
, lenW
, i
;
249 IStream_Read(stream
, &str_len
, sizeof(str_len
), &read_len
);
250 if (read_len
!= sizeof(str_len
))
260 if (!(buffer
= malloc(str_len
)))
261 return E_OUTOFMEMORY
;
263 IStream_Read(stream
, buffer
, str_len
, &read_len
);
264 if (read_len
!= str_len
)
270 /* Skip ansi buffer, it must be null terminated. */
272 while (i
< str_len
&& buffer
[i
])
277 WARN("Expected null terminated ansi name.\n");
286 if (str_len
% sizeof(WCHAR
))
288 WARN("Unexpected Unicode name length %ld.\n", str_len
);
293 str
= malloc(str_len
+ sizeof(WCHAR
));
296 memcpy(str
, &buffer
[i
+ 1], str_len
);
297 str
[str_len
/ sizeof(WCHAR
)] = 0;
302 lenW
= MultiByteToWideChar(CP_ACP
, 0, buffer
, -1, NULL
, 0);
303 str
= malloc(lenW
* sizeof(WCHAR
));
305 MultiByteToWideChar(CP_ACP
, 0, buffer
, -1, str
, lenW
);
322 /******************************************************************************
324 ******************************************************************************/
325 static HRESULT WINAPI
ItemMonikerImpl_Load(IMoniker
*iface
, IStream
*stream
)
327 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
330 TRACE("(%p, %p)\n", iface
, stream
);
332 /* Delimiter and name use the same record structure: 4 bytes byte-length field, followed by
333 string data. Data starts with single byte null-terminated string, WCHAR non-terminated
334 string optionally follows. Length of WCHAR string is determined as a difference between total
335 byte-length and single byte string length. */
337 hr
= item_moniker_load_string_record(stream
, &This
->itemDelimiter
);
339 hr
= item_moniker_load_string_record(stream
, &This
->itemName
);
344 /******************************************************************************
346 ******************************************************************************/
347 static HRESULT WINAPI
ItemMonikerImpl_Save(IMoniker
*iface
, IStream
*stream
, BOOL fClearDirty
)
349 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
354 TRACE("(%p, %p, %d)\n", iface
, stream
, fClearDirty
);
356 /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
357 /* 2) String (type A): item delimiter string ('\0' included) */
358 /* 3) DWORD : size of item name string ('\0' included) */
359 /* 4) String (type A): item name string ('\0' included) */
360 if (This
->itemDelimiter
)
362 str_len
= WideCharToMultiByte(CP_ACP
, 0, This
->itemDelimiter
, -1, NULL
, 0, NULL
, NULL
);
363 str
= malloc(str_len
);
364 WideCharToMultiByte(CP_ACP
, 0, This
->itemDelimiter
, -1, str
, str_len
, NULL
, NULL
);
366 hr
= IStream_Write(stream
, &str_len
, sizeof(str_len
), NULL
);
367 hr
= IStream_Write(stream
, str
, str_len
, NULL
);
374 hr
= IStream_Write(stream
, &str_len
, sizeof(str_len
), NULL
);
377 str_len
= WideCharToMultiByte(CP_ACP
, 0, This
->itemName
, -1, NULL
, 0, NULL
, NULL
);
378 str
= malloc(str_len
);
379 WideCharToMultiByte(CP_ACP
, 0, This
->itemName
, -1, str
, str_len
, NULL
, NULL
);
380 hr
= IStream_Write(stream
, &str_len
, sizeof(str_len
), NULL
);
381 hr
= IStream_Write(stream
, str
, str_len
, NULL
);
387 /******************************************************************************
388 * ItemMoniker_GetSizeMax
389 ******************************************************************************/
390 static HRESULT WINAPI
ItemMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
)
392 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
393 DWORD nameLength
=lstrlenW(This
->itemName
)+1;
395 TRACE("(%p,%p)\n",iface
,pcbSize
);
400 /* for more details see ItemMonikerImpl_Save comments */
402 pcbSize
->u
.LowPart
= sizeof(DWORD
) + /* DWORD which contains delimiter length */
403 sizeof(DWORD
) + /* DWORD which contains item name length */
404 nameLength
*4 + /* item name string */
405 18; /* strange, but true */
406 if (This
->itemDelimiter
)
407 pcbSize
->u
.LowPart
+= (lstrlenW(This
->itemDelimiter
) + 1) * 4;
409 pcbSize
->u
.HighPart
=0;
414 static DWORD
get_bind_speed_from_bindctx(IBindCtx
*pbc
)
416 DWORD bind_speed
= BINDSPEED_INDEFINITE
;
419 bind_opts
.cbStruct
= sizeof(bind_opts
);
420 if (SUCCEEDED(IBindCtx_GetBindOptions(pbc
, &bind_opts
)) && bind_opts
.dwTickCountDeadline
)
421 bind_speed
= bind_opts
.dwTickCountDeadline
< 2500 ? BINDSPEED_IMMEDIATE
: BINDSPEED_MODERATE
;
426 /******************************************************************************
427 * ItemMoniker_BindToObject
428 ******************************************************************************/
429 static HRESULT WINAPI
ItemMonikerImpl_BindToObject(IMoniker
* iface
,
435 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
436 IOleItemContainer
*container
;
439 TRACE("(%p,%p,%p,%s,%p)\n",iface
,pbc
,pmkToLeft
,debugstr_guid(riid
),ppvResult
);
449 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
452 if (FAILED(hr
= set_container_lock(container
, pbc
)))
453 WARN("Failed to lock container, hr %#lx.\n", hr
);
455 hr
= IOleItemContainer_GetObject(container
, This
->itemName
, get_bind_speed_from_bindctx(pbc
), pbc
,
457 IOleItemContainer_Release(container
);
463 /******************************************************************************
464 * ItemMoniker_BindToStorage
465 ******************************************************************************/
466 static HRESULT WINAPI
ItemMonikerImpl_BindToStorage(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
, REFIID riid
,
469 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
470 IOleItemContainer
*container
;
473 TRACE("%p, %p, %p, %s, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_guid(riid
), ppvResult
);
480 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
483 if (FAILED(hr
= set_container_lock(container
, pbc
)))
484 WARN("Failed to lock container, hr %#lx.\n", hr
);
486 hr
= IOleItemContainer_GetObjectStorage(container
, moniker
->itemName
, pbc
, riid
, ppvResult
);
487 IOleItemContainer_Release(container
);
493 static HRESULT WINAPI
ItemMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
,
494 DWORD dwReduceHowFar
, IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
496 TRACE("%p, %p, %ld, %p, %p.\n", iface
, pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
498 if (ppmkReduced
==NULL
)
501 ItemMonikerImpl_AddRef(iface
);
505 return MK_S_REDUCED_TO_SELF
;
508 static HRESULT WINAPI
ItemMonikerImpl_ComposeWith(IMoniker
*iface
, IMoniker
*right
,
509 BOOL only_if_not_generic
, IMoniker
**result
)
513 TRACE("%p, %p, %d, %p\n", iface
, right
, only_if_not_generic
, result
);
515 if (!result
|| !right
)
520 if (is_anti_moniker(right
, &order
))
521 return order
> 1 ? create_anti_moniker(order
- 1, result
) : S_OK
;
523 return only_if_not_generic
? MK_E_NEEDGENERIC
: CreateGenericComposite(iface
, right
, result
);
526 /******************************************************************************
528 ******************************************************************************/
529 static HRESULT WINAPI
ItemMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
531 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
533 if (ppenumMoniker
== NULL
)
536 *ppenumMoniker
= NULL
;
541 /******************************************************************************
542 * ItemMoniker_IsEqual
543 ******************************************************************************/
544 static HRESULT WINAPI
ItemMonikerImpl_IsEqual(IMoniker
*iface
, IMoniker
*other
)
546 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
548 TRACE("%p, %p.\n", iface
, other
);
553 other_moniker
= unsafe_impl_from_IMoniker(other
);
557 return !wcsicmp(moniker
->itemName
, other_moniker
->itemName
) ? S_OK
: S_FALSE
;
560 /******************************************************************************
562 ******************************************************************************/
563 static HRESULT WINAPI
ItemMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
565 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
574 val
= This
->itemName
;
577 for (i
= len
; i
> 0; i
--)
578 h
= (h
* 3) ^ towupper(val
[off
++]);
585 /******************************************************************************
586 * ItemMoniker_IsRunning
587 ******************************************************************************/
588 static HRESULT WINAPI
ItemMonikerImpl_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
,
589 IMoniker
*pmkNewlyRunning
)
591 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
592 IOleItemContainer
*container
;
593 IRunningObjectTable
* rot
;
596 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
605 return IMoniker_IsEqual(iface
, pmkNewlyRunning
);
609 hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
);
612 hr
= IRunningObjectTable_IsRunning(rot
, iface
);
613 IRunningObjectTable_Release(rot
);
619 /* Container itself must be running too. */
620 hr
= IMoniker_IsRunning(pmkToLeft
, pbc
, NULL
, NULL
);
624 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
627 hr
= IOleItemContainer_IsRunning(container
, moniker
->itemName
);
628 IOleItemContainer_Release(container
);
635 /******************************************************************************
636 * ItemMoniker_GetTimeOfLastChange
637 ******************************************************************************/
638 static HRESULT WINAPI
ItemMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
643 IRunningObjectTable
* rot
;
645 IMoniker
*compositeMk
;
647 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pItemTime
);
652 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
655 return MK_E_NOTBINDABLE
;
658 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
659 /* the time of last change. If the object is not in the ROT, the method calls */
660 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
662 res
=CreateGenericComposite(pmkToLeft
,iface
,&compositeMk
);
666 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
668 IMoniker_Release(compositeMk
);
672 if (IRunningObjectTable_GetTimeOfLastChange(rot
,compositeMk
,pItemTime
)!=S_OK
)
674 res
=IMoniker_GetTimeOfLastChange(pmkToLeft
,pbc
,NULL
,pItemTime
);
676 IMoniker_Release(compositeMk
);
682 /******************************************************************************
683 * ItemMoniker_Inverse
684 ******************************************************************************/
685 static HRESULT WINAPI
ItemMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
687 TRACE("(%p,%p)\n",iface
,ppmk
);
692 return CreateAntiMoniker(ppmk
);
695 static HRESULT WINAPI
ItemMonikerImpl_CommonPrefixWith(IMoniker
*iface
, IMoniker
*other
,
698 TRACE("%p, %p, %p\n", iface
, other
, prefix
);
700 if (IMoniker_IsEqual(iface
, other
) == S_OK
)
703 IMoniker_AddRef(iface
);
707 return MonikerCommonPrefixWith(iface
, other
, prefix
);
710 static HRESULT WINAPI
ItemMonikerImpl_RelativePathTo(IMoniker
*iface
, IMoniker
*other
, IMoniker
**result
)
712 TRACE("%p, %p, %p.\n", iface
, other
, result
);
714 if (!other
|| !result
)
719 return MK_E_NOTBINDABLE
;
722 /******************************************************************************
723 * ItemMoniker_GetDisplayName
724 ******************************************************************************/
725 static HRESULT WINAPI
ItemMonikerImpl_GetDisplayName(IMoniker
* iface
,
728 LPOLESTR
*ppszDisplayName
)
730 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
733 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
735 if (ppszDisplayName
==NULL
)
738 if (pmkToLeft
!=NULL
){
742 size
= lstrlenW(This
->itemName
) + 1;
743 if (This
->itemDelimiter
)
744 size
+= lstrlenW(This
->itemDelimiter
);
745 size
*= sizeof(WCHAR
);
747 *ppszDisplayName
= CoTaskMemAlloc(size
);
748 if (*ppszDisplayName
==NULL
)
749 return E_OUTOFMEMORY
;
751 (*ppszDisplayName
)[0] = 0;
752 if (This
->itemDelimiter
)
753 lstrcatW(*ppszDisplayName
, This
->itemDelimiter
);
754 lstrcatW(*ppszDisplayName
,This
->itemName
);
756 TRACE("-- %s\n", debugstr_w(*ppszDisplayName
));
761 /******************************************************************************
762 * ItemMoniker_ParseDisplayName
763 ******************************************************************************/
764 static HRESULT WINAPI
ItemMonikerImpl_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
,
765 LPOLESTR displayname
, ULONG
*eaten
, IMoniker
**ppmkOut
)
767 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
768 IOleItemContainer
*container
;
769 IParseDisplayName
*parser
;
772 TRACE("%p, %p, %p, %s, %p, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_w(displayname
), eaten
, ppmkOut
);
777 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
780 if (SUCCEEDED(hr
= set_container_lock(container
, pbc
)))
782 hr
= IOleItemContainer_GetObject(container
, This
->itemName
, get_bind_speed_from_bindctx(pbc
), pbc
,
783 &IID_IParseDisplayName
, (void **)&parser
);
786 hr
= IParseDisplayName_ParseDisplayName(parser
, pbc
, displayname
, eaten
, ppmkOut
);
787 IParseDisplayName_Release(parser
);
790 IOleItemContainer_Release(container
);
796 /******************************************************************************
797 * ItemMoniker_IsSystemMoniker
798 ******************************************************************************/
799 static HRESULT WINAPI
ItemMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
801 TRACE("(%p,%p)\n",iface
,pwdMksys
);
806 (*pwdMksys
)=MKSYS_ITEMMONIKER
;
811 /*******************************************************************************
812 * ItemMonikerIROTData_QueryInterface
813 *******************************************************************************/
814 static HRESULT WINAPI
ItemMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
818 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
820 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppvObject
);
822 return ItemMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
825 /***********************************************************************
826 * ItemMonikerIROTData_AddRef
828 static ULONG WINAPI
ItemMonikerROTDataImpl_AddRef(IROTData
*iface
)
830 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
832 TRACE("(%p)\n",iface
);
834 return ItemMonikerImpl_AddRef(&This
->IMoniker_iface
);
837 /***********************************************************************
838 * ItemMonikerIROTData_Release
840 static ULONG WINAPI
ItemMonikerROTDataImpl_Release(IROTData
* iface
)
842 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
844 TRACE("(%p)\n",iface
);
846 return ItemMonikerImpl_Release(&This
->IMoniker_iface
);
849 /******************************************************************************
850 * ItemMonikerIROTData_GetComparisonData
851 ******************************************************************************/
852 static HRESULT WINAPI
ItemMonikerROTDataImpl_GetComparisonData(IROTData
*iface
, BYTE
*buffer
, ULONG max_len
,
855 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
856 int name_len
= lstrlenW(This
->itemName
);
860 TRACE("%p, %p, %lu, %p.\n", iface
, buffer
, max_len
, data_len
);
862 delim_len
= This
->itemDelimiter
&& This
->itemDelimiter
[0] ? lstrlenW(This
->itemDelimiter
) : 0;
863 *data_len
= sizeof(CLSID
) + sizeof(WCHAR
) + (delim_len
+ name_len
) * sizeof(WCHAR
);
864 if (max_len
< *data_len
)
865 return E_OUTOFMEMORY
;
868 memcpy(buffer
, &CLSID_ItemMoniker
, sizeof(CLSID
));
869 buffer
+= sizeof(CLSID
);
871 /* write delimiter */
872 for (i
= 0, ptrW
= (WCHAR
*)buffer
; i
< delim_len
; ++i
)
873 ptrW
[i
] = towupper(This
->itemDelimiter
[i
]);
874 buffer
+= (delim_len
* sizeof(WCHAR
));
877 for (i
= 0, ptrW
= (WCHAR
*)buffer
; i
< name_len
; ++i
)
878 ptrW
[i
] = towupper(This
->itemName
[i
]);
884 /********************************************************************************/
885 /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/
886 /* IPersistStream and IMoniker functions. */
887 static const IMonikerVtbl VT_ItemMonikerImpl
=
889 ItemMonikerImpl_QueryInterface
,
890 ItemMonikerImpl_AddRef
,
891 ItemMonikerImpl_Release
,
892 ItemMonikerImpl_GetClassID
,
893 ItemMonikerImpl_IsDirty
,
894 ItemMonikerImpl_Load
,
895 ItemMonikerImpl_Save
,
896 ItemMonikerImpl_GetSizeMax
,
897 ItemMonikerImpl_BindToObject
,
898 ItemMonikerImpl_BindToStorage
,
899 ItemMonikerImpl_Reduce
,
900 ItemMonikerImpl_ComposeWith
,
901 ItemMonikerImpl_Enum
,
902 ItemMonikerImpl_IsEqual
,
903 ItemMonikerImpl_Hash
,
904 ItemMonikerImpl_IsRunning
,
905 ItemMonikerImpl_GetTimeOfLastChange
,
906 ItemMonikerImpl_Inverse
,
907 ItemMonikerImpl_CommonPrefixWith
,
908 ItemMonikerImpl_RelativePathTo
,
909 ItemMonikerImpl_GetDisplayName
,
910 ItemMonikerImpl_ParseDisplayName
,
911 ItemMonikerImpl_IsSystemMoniker
914 static ItemMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
)
916 if (iface
->lpVtbl
!= &VT_ItemMonikerImpl
)
918 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IMoniker_iface
);
921 /********************************************************************************/
922 /* Virtual function table for the IROTData class. */
923 static const IROTDataVtbl VT_ROTDataImpl
=
925 ItemMonikerROTDataImpl_QueryInterface
,
926 ItemMonikerROTDataImpl_AddRef
,
927 ItemMonikerROTDataImpl_Release
,
928 ItemMonikerROTDataImpl_GetComparisonData
931 /******************************************************************************
932 * CreateItemMoniker [OLE32.@]
933 ******************************************************************************/
934 HRESULT WINAPI
CreateItemMoniker(const WCHAR
*delimiter
, const WCHAR
*name
, IMoniker
**ret
)
936 ItemMonikerImpl
*moniker
;
940 TRACE("%s, %s, %p.\n", debugstr_w(delimiter
), debugstr_w(name
), ret
);
942 if (!(moniker
= calloc(1, sizeof(*moniker
))))
943 return E_OUTOFMEMORY
;
945 moniker
->IMoniker_iface
.lpVtbl
= &VT_ItemMonikerImpl
;
946 moniker
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
949 str_len
= (lstrlenW(name
) + 1) * sizeof(WCHAR
);
950 moniker
->itemName
= malloc(str_len
);
951 if (!moniker
->itemName
)
956 memcpy(moniker
->itemName
, name
, str_len
);
960 str_len
= (lstrlenW(delimiter
) + 1) * sizeof(WCHAR
);
961 moniker
->itemDelimiter
= malloc(str_len
);
962 if (!moniker
->itemDelimiter
)
967 memcpy(moniker
->itemDelimiter
, delimiter
, str_len
);
970 *ret
= &moniker
->IMoniker_iface
;
975 IMoniker_Release(&moniker
->IMoniker_iface
);
980 HRESULT WINAPI
ItemMoniker_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
985 TRACE("(%p, %s, %p)\n", outer
, debugstr_guid(riid
), ppv
);
990 return CLASS_E_NOAGGREGATION
;
992 if (FAILED(hr
= CreateItemMoniker(L
"", L
"", &moniker
)))
995 hr
= IMoniker_QueryInterface(moniker
, riid
, ppv
);
996 IMoniker_Release(moniker
);