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
31 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
37 /* ItemMoniker data structure */
38 typedef struct ItemMonikerImpl
{
39 IMoniker IMoniker_iface
; /* VTable relative to the IMoniker interface.*/
40 IROTData IROTData_iface
; /* VTable relative to the IROTData interface.*/
42 LPOLESTR itemName
; /* item name identified by this ItemMoniker */
43 LPOLESTR itemDelimiter
; /* Delimiter string */
44 IUnknown
*pMarshal
; /* custom marshaler */
47 static inline ItemMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
49 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IMoniker_iface
);
52 static ItemMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
);
54 static inline ItemMonikerImpl
*impl_from_IROTData(IROTData
*iface
)
56 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IROTData_iface
);
61 IUnknown IUnknown_iface
;
63 IOleItemContainer
*container
;
66 static struct container_lock
*impl_lock_from_IUnknown(IUnknown
*iface
)
68 return CONTAINING_RECORD(iface
, struct container_lock
, IUnknown_iface
);
71 static HRESULT WINAPI
container_lock_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
73 if (IsEqualIID(riid
, &IID_IUnknown
))
76 IUnknown_AddRef(iface
);
80 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
85 static ULONG WINAPI
container_lock_AddRef(IUnknown
*iface
)
87 struct container_lock
*lock
= impl_lock_from_IUnknown(iface
);
88 return InterlockedIncrement(&lock
->refcount
);
91 static ULONG WINAPI
container_lock_Release(IUnknown
*iface
)
93 struct container_lock
*lock
= impl_lock_from_IUnknown(iface
);
94 ULONG refcount
= InterlockedDecrement(&lock
->refcount
);
98 IOleItemContainer_LockContainer(lock
->container
, FALSE
);
99 IOleItemContainer_Release(lock
->container
);
106 static const IUnknownVtbl container_lock_vtbl
=
108 container_lock_QueryInterface
,
109 container_lock_AddRef
,
110 container_lock_Release
,
113 static HRESULT
set_container_lock(IOleItemContainer
*container
, IBindCtx
*pbc
)
115 struct container_lock
*lock
;
118 if (!(lock
= malloc(sizeof(*lock
))))
119 return E_OUTOFMEMORY
;
121 if (FAILED(hr
= IOleItemContainer_LockContainer(container
, TRUE
)))
127 lock
->IUnknown_iface
.lpVtbl
= &container_lock_vtbl
;
129 lock
->container
= container
;
130 IOleItemContainer_AddRef(lock
->container
);
132 hr
= IBindCtx_RegisterObjectBound(pbc
, &lock
->IUnknown_iface
);
133 IUnknown_Release(&lock
->IUnknown_iface
);
137 /*******************************************************************************
138 * ItemMoniker_QueryInterface
139 *******************************************************************************/
140 static HRESULT WINAPI
ItemMonikerImpl_QueryInterface(IMoniker
*iface
, REFIID riid
, void **ppvObject
)
142 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
144 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppvObject
);
149 if (IsEqualIID(&IID_IUnknown
, riid
) ||
150 IsEqualIID(&IID_IPersist
, riid
) ||
151 IsEqualIID(&IID_IPersistStream
, riid
) ||
152 IsEqualIID(&IID_IMoniker
, riid
) ||
153 IsEqualGUID(&CLSID_ItemMoniker
, riid
))
157 else if (IsEqualIID(&IID_IROTData
, riid
))
158 *ppvObject
= &This
->IROTData_iface
;
159 else if (IsEqualIID(&IID_IMarshal
, riid
))
163 hr
= MonikerMarshal_Create(iface
, &This
->pMarshal
);
166 return IUnknown_QueryInterface(This
->pMarshal
, riid
, ppvObject
);
171 return E_NOINTERFACE
;
174 IMoniker_AddRef(iface
);
178 /******************************************************************************
180 ******************************************************************************/
181 static ULONG WINAPI
ItemMonikerImpl_AddRef(IMoniker
* iface
)
183 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
185 TRACE("(%p)\n",This
);
187 return InterlockedIncrement(&This
->ref
);
190 /******************************************************************************
191 * ItemMoniker_Release
192 ******************************************************************************/
193 static ULONG WINAPI
ItemMonikerImpl_Release(IMoniker
* iface
)
195 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
196 ULONG refcount
= InterlockedDecrement(&moniker
->ref
);
198 TRACE("%p, refcount %lu.\n", iface
, refcount
);
202 if (moniker
->pMarshal
) IUnknown_Release(moniker
->pMarshal
);
203 free(moniker
->itemName
);
204 free(moniker
->itemDelimiter
);
211 /******************************************************************************
212 * ItemMoniker_GetClassID
213 ******************************************************************************/
214 static HRESULT WINAPI
ItemMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
216 TRACE("(%p,%p)\n",iface
,pClassID
);
221 *pClassID
= CLSID_ItemMoniker
;
226 /******************************************************************************
227 * ItemMoniker_IsDirty
228 ******************************************************************************/
229 static HRESULT WINAPI
ItemMonikerImpl_IsDirty(IMoniker
* iface
)
231 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
232 method in the OLE-provided moniker interfaces always return S_FALSE because
233 their internal state never changes. */
235 TRACE("(%p)\n",iface
);
240 static HRESULT
item_moniker_load_string_record(IStream
*stream
, WCHAR
**ret
)
242 DWORD str_len
, read_len
, lenW
, i
;
247 IStream_Read(stream
, &str_len
, sizeof(str_len
), &read_len
);
248 if (read_len
!= sizeof(str_len
))
258 if (!(buffer
= malloc(str_len
)))
259 return E_OUTOFMEMORY
;
261 IStream_Read(stream
, buffer
, str_len
, &read_len
);
262 if (read_len
!= str_len
)
268 /* Skip ansi buffer, it must be null terminated. */
270 while (i
< str_len
&& buffer
[i
])
275 WARN("Expected null terminated ansi name.\n");
284 if (str_len
% sizeof(WCHAR
))
286 WARN("Unexpected Unicode name length %ld.\n", str_len
);
291 str
= malloc(str_len
+ sizeof(WCHAR
));
294 memcpy(str
, &buffer
[i
+ 1], str_len
);
295 str
[str_len
/ sizeof(WCHAR
)] = 0;
300 lenW
= MultiByteToWideChar(CP_ACP
, 0, buffer
, -1, NULL
, 0);
301 str
= malloc(lenW
* sizeof(WCHAR
));
303 MultiByteToWideChar(CP_ACP
, 0, buffer
, -1, str
, lenW
);
320 /******************************************************************************
322 ******************************************************************************/
323 static HRESULT WINAPI
ItemMonikerImpl_Load(IMoniker
*iface
, IStream
*stream
)
325 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
328 TRACE("(%p, %p)\n", iface
, stream
);
330 /* Delimiter and name use the same record structure: 4 bytes byte-length field, followed by
331 string data. Data starts with single byte null-terminated string, WCHAR non-terminated
332 string optionally follows. Length of WCHAR string is determined as a difference between total
333 byte-length and single byte string length. */
335 hr
= item_moniker_load_string_record(stream
, &This
->itemDelimiter
);
337 hr
= item_moniker_load_string_record(stream
, &This
->itemName
);
342 /******************************************************************************
344 ******************************************************************************/
345 static HRESULT WINAPI
ItemMonikerImpl_Save(IMoniker
*iface
, IStream
*stream
, BOOL fClearDirty
)
347 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
352 TRACE("(%p, %p, %d)\n", iface
, stream
, fClearDirty
);
354 /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
355 /* 2) String (type A): item delimiter string ('\0' included) */
356 /* 3) DWORD : size of item name string ('\0' included) */
357 /* 4) String (type A): item name string ('\0' included) */
358 if (This
->itemDelimiter
)
360 str_len
= WideCharToMultiByte(CP_ACP
, 0, This
->itemDelimiter
, -1, NULL
, 0, NULL
, NULL
);
361 str
= malloc(str_len
);
362 WideCharToMultiByte(CP_ACP
, 0, This
->itemDelimiter
, -1, str
, str_len
, NULL
, NULL
);
364 hr
= IStream_Write(stream
, &str_len
, sizeof(str_len
), NULL
);
365 hr
= IStream_Write(stream
, str
, str_len
, NULL
);
372 hr
= IStream_Write(stream
, &str_len
, sizeof(str_len
), NULL
);
375 str_len
= WideCharToMultiByte(CP_ACP
, 0, This
->itemName
, -1, NULL
, 0, NULL
, NULL
);
376 str
= malloc(str_len
);
377 WideCharToMultiByte(CP_ACP
, 0, This
->itemName
, -1, str
, str_len
, NULL
, NULL
);
378 hr
= IStream_Write(stream
, &str_len
, sizeof(str_len
), NULL
);
379 hr
= IStream_Write(stream
, str
, str_len
, NULL
);
385 /******************************************************************************
386 * ItemMoniker_GetSizeMax
387 ******************************************************************************/
388 static HRESULT WINAPI
ItemMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
)
390 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
391 DWORD nameLength
=lstrlenW(This
->itemName
)+1;
393 TRACE("(%p,%p)\n",iface
,pcbSize
);
398 /* for more details see ItemMonikerImpl_Save comments */
400 pcbSize
->u
.LowPart
= sizeof(DWORD
) + /* DWORD which contains delimiter length */
401 sizeof(DWORD
) + /* DWORD which contains item name length */
402 nameLength
*4 + /* item name string */
403 18; /* strange, but true */
404 if (This
->itemDelimiter
)
405 pcbSize
->u
.LowPart
+= (lstrlenW(This
->itemDelimiter
) + 1) * 4;
407 pcbSize
->u
.HighPart
=0;
412 static DWORD
get_bind_speed_from_bindctx(IBindCtx
*pbc
)
414 DWORD bind_speed
= BINDSPEED_INDEFINITE
;
417 bind_opts
.cbStruct
= sizeof(bind_opts
);
418 if (SUCCEEDED(IBindCtx_GetBindOptions(pbc
, &bind_opts
)) && bind_opts
.dwTickCountDeadline
)
419 bind_speed
= bind_opts
.dwTickCountDeadline
< 2500 ? BINDSPEED_IMMEDIATE
: BINDSPEED_MODERATE
;
424 /******************************************************************************
425 * ItemMoniker_BindToObject
426 ******************************************************************************/
427 static HRESULT WINAPI
ItemMonikerImpl_BindToObject(IMoniker
* iface
,
433 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
434 IOleItemContainer
*container
;
437 TRACE("(%p,%p,%p,%s,%p)\n",iface
,pbc
,pmkToLeft
,debugstr_guid(riid
),ppvResult
);
447 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
450 if (FAILED(hr
= set_container_lock(container
, pbc
)))
451 WARN("Failed to lock container, hr %#lx.\n", hr
);
453 hr
= IOleItemContainer_GetObject(container
, This
->itemName
, get_bind_speed_from_bindctx(pbc
), pbc
,
455 IOleItemContainer_Release(container
);
461 /******************************************************************************
462 * ItemMoniker_BindToStorage
463 ******************************************************************************/
464 static HRESULT WINAPI
ItemMonikerImpl_BindToStorage(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
, REFIID riid
,
467 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
468 IOleItemContainer
*container
;
471 TRACE("%p, %p, %p, %s, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_guid(riid
), ppvResult
);
478 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
481 if (FAILED(hr
= set_container_lock(container
, pbc
)))
482 WARN("Failed to lock container, hr %#lx.\n", hr
);
484 hr
= IOleItemContainer_GetObjectStorage(container
, moniker
->itemName
, pbc
, riid
, ppvResult
);
485 IOleItemContainer_Release(container
);
491 static HRESULT WINAPI
ItemMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
,
492 DWORD dwReduceHowFar
, IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
494 TRACE("%p, %p, %ld, %p, %p.\n", iface
, pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
496 if (ppmkReduced
==NULL
)
499 ItemMonikerImpl_AddRef(iface
);
503 return MK_S_REDUCED_TO_SELF
;
506 static HRESULT WINAPI
ItemMonikerImpl_ComposeWith(IMoniker
*iface
, IMoniker
*right
,
507 BOOL only_if_not_generic
, IMoniker
**result
)
511 TRACE("%p, %p, %d, %p\n", iface
, right
, only_if_not_generic
, result
);
513 if (!result
|| !right
)
518 if (is_anti_moniker(right
, &order
))
519 return order
> 1 ? create_anti_moniker(order
- 1, result
) : S_OK
;
521 return only_if_not_generic
? MK_E_NEEDGENERIC
: CreateGenericComposite(iface
, right
, result
);
524 /******************************************************************************
526 ******************************************************************************/
527 static HRESULT WINAPI
ItemMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
529 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
531 if (ppenumMoniker
== NULL
)
534 *ppenumMoniker
= NULL
;
539 /******************************************************************************
540 * ItemMoniker_IsEqual
541 ******************************************************************************/
542 static HRESULT WINAPI
ItemMonikerImpl_IsEqual(IMoniker
*iface
, IMoniker
*other
)
544 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
546 TRACE("%p, %p.\n", iface
, other
);
551 other_moniker
= unsafe_impl_from_IMoniker(other
);
555 return !wcsicmp(moniker
->itemName
, other_moniker
->itemName
) ? S_OK
: S_FALSE
;
558 /******************************************************************************
560 ******************************************************************************/
561 static HRESULT WINAPI
ItemMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
563 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
572 val
= This
->itemName
;
575 for (i
= len
; i
> 0; i
--)
576 h
= (h
* 3) ^ towupper(val
[off
++]);
583 /******************************************************************************
584 * ItemMoniker_IsRunning
585 ******************************************************************************/
586 static HRESULT WINAPI
ItemMonikerImpl_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
,
587 IMoniker
*pmkNewlyRunning
)
589 ItemMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
590 IOleItemContainer
*container
;
591 IRunningObjectTable
* rot
;
594 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
603 return IMoniker_IsEqual(iface
, pmkNewlyRunning
);
607 hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
);
610 hr
= IRunningObjectTable_IsRunning(rot
, iface
);
611 IRunningObjectTable_Release(rot
);
617 /* Container itself must be running too. */
618 hr
= IMoniker_IsRunning(pmkToLeft
, pbc
, NULL
, NULL
);
622 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
625 hr
= IOleItemContainer_IsRunning(container
, moniker
->itemName
);
626 IOleItemContainer_Release(container
);
633 /******************************************************************************
634 * ItemMoniker_GetTimeOfLastChange
635 ******************************************************************************/
636 static HRESULT WINAPI
ItemMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
641 IRunningObjectTable
* rot
;
643 IMoniker
*compositeMk
;
645 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pItemTime
);
650 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
653 return MK_E_NOTBINDABLE
;
656 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
657 /* the time of last change. If the object is not in the ROT, the method calls */
658 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
660 res
=CreateGenericComposite(pmkToLeft
,iface
,&compositeMk
);
664 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
666 IMoniker_Release(compositeMk
);
670 if (IRunningObjectTable_GetTimeOfLastChange(rot
,compositeMk
,pItemTime
)!=S_OK
)
672 res
=IMoniker_GetTimeOfLastChange(pmkToLeft
,pbc
,NULL
,pItemTime
);
674 IMoniker_Release(compositeMk
);
680 /******************************************************************************
681 * ItemMoniker_Inverse
682 ******************************************************************************/
683 static HRESULT WINAPI
ItemMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
685 TRACE("(%p,%p)\n",iface
,ppmk
);
690 return CreateAntiMoniker(ppmk
);
693 static HRESULT WINAPI
ItemMonikerImpl_CommonPrefixWith(IMoniker
*iface
, IMoniker
*other
,
696 TRACE("%p, %p, %p\n", iface
, other
, prefix
);
698 if (IMoniker_IsEqual(iface
, other
) == S_OK
)
701 IMoniker_AddRef(iface
);
705 return MonikerCommonPrefixWith(iface
, other
, prefix
);
708 static HRESULT WINAPI
ItemMonikerImpl_RelativePathTo(IMoniker
*iface
, IMoniker
*other
, IMoniker
**result
)
710 TRACE("%p, %p, %p.\n", iface
, other
, result
);
712 if (!other
|| !result
)
717 return MK_E_NOTBINDABLE
;
720 /******************************************************************************
721 * ItemMoniker_GetDisplayName
722 ******************************************************************************/
723 static HRESULT WINAPI
ItemMonikerImpl_GetDisplayName(IMoniker
* iface
,
726 LPOLESTR
*ppszDisplayName
)
728 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
731 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
733 if (ppszDisplayName
==NULL
)
736 if (pmkToLeft
!=NULL
){
740 size
= lstrlenW(This
->itemName
) + 1;
741 if (This
->itemDelimiter
)
742 size
+= lstrlenW(This
->itemDelimiter
);
743 size
*= sizeof(WCHAR
);
745 *ppszDisplayName
= CoTaskMemAlloc(size
);
746 if (*ppszDisplayName
==NULL
)
747 return E_OUTOFMEMORY
;
749 (*ppszDisplayName
)[0] = 0;
750 if (This
->itemDelimiter
)
751 lstrcatW(*ppszDisplayName
, This
->itemDelimiter
);
752 lstrcatW(*ppszDisplayName
,This
->itemName
);
754 TRACE("-- %s\n", debugstr_w(*ppszDisplayName
));
759 /******************************************************************************
760 * ItemMoniker_ParseDisplayName
761 ******************************************************************************/
762 static HRESULT WINAPI
ItemMonikerImpl_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
, IMoniker
*pmkToLeft
,
763 LPOLESTR displayname
, ULONG
*eaten
, IMoniker
**ppmkOut
)
765 ItemMonikerImpl
*This
= impl_from_IMoniker(iface
);
766 IOleItemContainer
*container
;
767 IParseDisplayName
*parser
;
770 TRACE("%p, %p, %p, %s, %p, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_w(displayname
), eaten
, ppmkOut
);
775 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IOleItemContainer
, (void **)&container
);
778 if (SUCCEEDED(hr
= set_container_lock(container
, pbc
)))
780 hr
= IOleItemContainer_GetObject(container
, This
->itemName
, get_bind_speed_from_bindctx(pbc
), pbc
,
781 &IID_IParseDisplayName
, (void **)&parser
);
784 hr
= IParseDisplayName_ParseDisplayName(parser
, pbc
, displayname
, eaten
, ppmkOut
);
785 IParseDisplayName_Release(parser
);
788 IOleItemContainer_Release(container
);
794 /******************************************************************************
795 * ItemMoniker_IsSystemMoniker
796 ******************************************************************************/
797 static HRESULT WINAPI
ItemMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
799 TRACE("(%p,%p)\n",iface
,pwdMksys
);
804 (*pwdMksys
)=MKSYS_ITEMMONIKER
;
809 /*******************************************************************************
810 * ItemMonikerIROTData_QueryInterface
811 *******************************************************************************/
812 static HRESULT WINAPI
ItemMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
816 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
818 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppvObject
);
820 return ItemMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
823 /***********************************************************************
824 * ItemMonikerIROTData_AddRef
826 static ULONG WINAPI
ItemMonikerROTDataImpl_AddRef(IROTData
*iface
)
828 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
830 TRACE("(%p)\n",iface
);
832 return ItemMonikerImpl_AddRef(&This
->IMoniker_iface
);
835 /***********************************************************************
836 * ItemMonikerIROTData_Release
838 static ULONG WINAPI
ItemMonikerROTDataImpl_Release(IROTData
* iface
)
840 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
842 TRACE("(%p)\n",iface
);
844 return ItemMonikerImpl_Release(&This
->IMoniker_iface
);
847 /******************************************************************************
848 * ItemMonikerIROTData_GetComparisonData
849 ******************************************************************************/
850 static HRESULT WINAPI
ItemMonikerROTDataImpl_GetComparisonData(IROTData
*iface
, BYTE
*buffer
, ULONG max_len
,
853 ItemMonikerImpl
*This
= impl_from_IROTData(iface
);
854 int name_len
= lstrlenW(This
->itemName
);
858 TRACE("%p, %p, %lu, %p.\n", iface
, buffer
, max_len
, data_len
);
860 delim_len
= This
->itemDelimiter
&& This
->itemDelimiter
[0] ? lstrlenW(This
->itemDelimiter
) : 0;
861 *data_len
= sizeof(CLSID
) + sizeof(WCHAR
) + (delim_len
+ name_len
) * sizeof(WCHAR
);
862 if (max_len
< *data_len
)
863 return E_OUTOFMEMORY
;
866 memcpy(buffer
, &CLSID_ItemMoniker
, sizeof(CLSID
));
867 buffer
+= sizeof(CLSID
);
869 /* write delimiter */
870 for (i
= 0, ptrW
= (WCHAR
*)buffer
; i
< delim_len
; ++i
)
871 ptrW
[i
] = towupper(This
->itemDelimiter
[i
]);
872 buffer
+= (delim_len
* sizeof(WCHAR
));
875 for (i
= 0, ptrW
= (WCHAR
*)buffer
; i
< name_len
; ++i
)
876 ptrW
[i
] = towupper(This
->itemName
[i
]);
882 /********************************************************************************/
883 /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/
884 /* IPersistStream and IMoniker functions. */
885 static const IMonikerVtbl VT_ItemMonikerImpl
=
887 ItemMonikerImpl_QueryInterface
,
888 ItemMonikerImpl_AddRef
,
889 ItemMonikerImpl_Release
,
890 ItemMonikerImpl_GetClassID
,
891 ItemMonikerImpl_IsDirty
,
892 ItemMonikerImpl_Load
,
893 ItemMonikerImpl_Save
,
894 ItemMonikerImpl_GetSizeMax
,
895 ItemMonikerImpl_BindToObject
,
896 ItemMonikerImpl_BindToStorage
,
897 ItemMonikerImpl_Reduce
,
898 ItemMonikerImpl_ComposeWith
,
899 ItemMonikerImpl_Enum
,
900 ItemMonikerImpl_IsEqual
,
901 ItemMonikerImpl_Hash
,
902 ItemMonikerImpl_IsRunning
,
903 ItemMonikerImpl_GetTimeOfLastChange
,
904 ItemMonikerImpl_Inverse
,
905 ItemMonikerImpl_CommonPrefixWith
,
906 ItemMonikerImpl_RelativePathTo
,
907 ItemMonikerImpl_GetDisplayName
,
908 ItemMonikerImpl_ParseDisplayName
,
909 ItemMonikerImpl_IsSystemMoniker
912 static ItemMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
)
914 if (iface
->lpVtbl
!= &VT_ItemMonikerImpl
)
916 return CONTAINING_RECORD(iface
, ItemMonikerImpl
, IMoniker_iface
);
919 /********************************************************************************/
920 /* Virtual function table for the IROTData class. */
921 static const IROTDataVtbl VT_ROTDataImpl
=
923 ItemMonikerROTDataImpl_QueryInterface
,
924 ItemMonikerROTDataImpl_AddRef
,
925 ItemMonikerROTDataImpl_Release
,
926 ItemMonikerROTDataImpl_GetComparisonData
929 /******************************************************************************
930 * CreateItemMoniker [OLE32.@]
931 ******************************************************************************/
932 HRESULT WINAPI
CreateItemMoniker(const WCHAR
*delimiter
, const WCHAR
*name
, IMoniker
**ret
)
934 ItemMonikerImpl
*moniker
;
938 TRACE("%s, %s, %p.\n", debugstr_w(delimiter
), debugstr_w(name
), ret
);
940 if (!(moniker
= calloc(1, sizeof(*moniker
))))
941 return E_OUTOFMEMORY
;
943 moniker
->IMoniker_iface
.lpVtbl
= &VT_ItemMonikerImpl
;
944 moniker
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
947 str_len
= (lstrlenW(name
) + 1) * sizeof(WCHAR
);
948 moniker
->itemName
= malloc(str_len
);
949 if (!moniker
->itemName
)
954 memcpy(moniker
->itemName
, name
, str_len
);
958 str_len
= (lstrlenW(delimiter
) + 1) * sizeof(WCHAR
);
959 moniker
->itemDelimiter
= malloc(str_len
);
960 if (!moniker
->itemDelimiter
)
965 memcpy(moniker
->itemDelimiter
, delimiter
, str_len
);
968 *ret
= &moniker
->IMoniker_iface
;
973 IMoniker_Release(&moniker
->IMoniker_iface
);
978 HRESULT WINAPI
ItemMoniker_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
983 TRACE("(%p, %s, %p)\n", outer
, debugstr_guid(riid
), ppv
);
988 return CLASS_E_NOAGGREGATION
;
990 if (FAILED(hr
= CreateItemMoniker(L
"", L
"", &moniker
)))
993 hr
= IMoniker_QueryInterface(moniker
, riid
, ppv
);
994 IMoniker_Release(moniker
);