winevulkan: Update to VK spec version 1.2.195.
[wine.git] / dlls / ole32 / itemmoniker.c
blob1ab9c52dbfbe03af0eff9c20a16d2e2a5ed0db9e
1 /*
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
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <string.h>
25 #define COBJMACROS
26 #define NONAMELESSUNION
28 #include "winerror.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "winnls.h"
33 #include "wine/debug.h"
34 #include "wine/heap.h"
35 #include "ole2.h"
36 #include "moniker.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.*/
44 LONG ref;
45 LPOLESTR itemName; /* item name identified by this ItemMoniker */
46 LPOLESTR itemDelimiter; /* Delimiter string */
47 IUnknown *pMarshal; /* custom marshaler */
48 } ItemMonikerImpl;
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);
62 struct container_lock
64 IUnknown IUnknown_iface;
65 LONG refcount;
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))
78 *obj = iface;
79 IUnknown_AddRef(iface);
80 return S_OK;
83 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
84 *obj = NULL;
85 return E_NOINTERFACE;
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);
99 if (!refcount)
101 IOleItemContainer_LockContainer(lock->container, FALSE);
102 IOleItemContainer_Release(lock->container);
103 heap_free(lock);
106 return refcount;
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;
119 HRESULT hr;
121 if (!(lock = heap_alloc(sizeof(*lock))))
122 return E_OUTOFMEMORY;
124 if (FAILED(hr = IOleItemContainer_LockContainer(container, TRUE)))
126 heap_free(lock);
127 return hr;
130 lock->IUnknown_iface.lpVtbl = &container_lock_vtbl;
131 lock->refcount = 1;
132 lock->container = container;
133 IOleItemContainer_AddRef(lock->container);
135 hr = IBindCtx_RegisterObjectBound(pbc, &lock->IUnknown_iface);
136 IUnknown_Release(&lock->IUnknown_iface);
137 return hr;
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);
149 if (!ppvObject)
150 return E_INVALIDARG;
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))
158 *ppvObject = iface;
160 else if (IsEqualIID(&IID_IROTData, riid))
161 *ppvObject = &This->IROTData_iface;
162 else if (IsEqualIID(&IID_IMarshal, riid))
164 HRESULT hr = S_OK;
165 if (!This->pMarshal)
166 hr = MonikerMarshal_Create(iface, &This->pMarshal);
167 if (hr != S_OK)
168 return hr;
169 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
171 else
173 *ppvObject = NULL;
174 return E_NOINTERFACE;
177 IMoniker_AddRef(iface);
178 return S_OK;
181 /******************************************************************************
182 * ItemMoniker_AddRef
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);
203 if (!refcount)
205 if (moniker->pMarshal) IUnknown_Release(moniker->pMarshal);
206 heap_free(moniker->itemName);
207 heap_free(moniker->itemDelimiter);
208 heap_free(moniker);
211 return refcount;
214 /******************************************************************************
215 * ItemMoniker_GetClassID
216 ******************************************************************************/
217 static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
219 TRACE("(%p,%p)\n",iface,pClassID);
221 if (pClassID==NULL)
222 return E_POINTER;
224 *pClassID = CLSID_ItemMoniker;
226 return S_OK;
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);
240 return S_FALSE;
243 static HRESULT item_moniker_load_string_record(IStream *stream, WCHAR **ret)
245 DWORD str_len, read_len, lenW, i;
246 HRESULT hr = S_OK;
247 char *buffer;
248 WCHAR *str;
250 IStream_Read(stream, &str_len, sizeof(str_len), &read_len);
251 if (read_len != sizeof(str_len))
252 return E_FAIL;
254 if (!str_len)
256 heap_free(*ret);
257 *ret = NULL;
258 return S_OK;
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)
267 heap_free(buffer);
268 return E_FAIL;
271 /* Skip ansi buffer, it must be null terminated. */
272 i = 0;
273 while (i < str_len && buffer[i])
274 i++;
276 if (buffer[i])
278 WARN("Expected null terminated ansi name.\n");
279 hr = E_FAIL;
280 goto end;
283 if (i < str_len - 1)
285 str_len -= i + 1;
287 if (str_len % sizeof(WCHAR))
289 WARN("Unexpected Unicode name length %d.\n", str_len);
290 hr = E_FAIL;
291 goto end;
294 str = heap_alloc(str_len + sizeof(WCHAR));
295 if (str)
297 memcpy(str, &buffer[i + 1], str_len);
298 str[str_len / sizeof(WCHAR)] = 0;
301 else
303 lenW = MultiByteToWideChar(CP_ACP, 0, buffer, -1, NULL, 0);
304 str = heap_alloc(lenW * sizeof(WCHAR));
305 if (str)
306 MultiByteToWideChar(CP_ACP, 0, buffer, -1, str, lenW);
309 if (str)
311 heap_free(*ret);
312 *ret = str;
314 else
315 hr = E_OUTOFMEMORY;
317 end:
318 heap_free(buffer);
320 return hr;
323 /******************************************************************************
324 * ItemMoniker_Load
325 ******************************************************************************/
326 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker *iface, IStream *stream)
328 ItemMonikerImpl *This = impl_from_IMoniker(iface);
329 HRESULT hr;
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);
339 if (SUCCEEDED(hr))
340 hr = item_moniker_load_string_record(stream, &This->itemName);
342 return hr;
345 /******************************************************************************
346 * ItemMoniker_Save
347 ******************************************************************************/
348 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker *iface, IStream *stream, BOOL fClearDirty)
350 ItemMonikerImpl *This = impl_from_IMoniker(iface);
351 int str_len;
352 HRESULT hr;
353 char *str;
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);
370 heap_free(str);
372 else
374 str_len = 0;
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);
383 heap_free(str);
385 return hr;
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);
398 if (!pcbSize)
399 return E_POINTER;
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;
412 return S_OK;
415 static DWORD get_bind_speed_from_bindctx(IBindCtx *pbc)
417 DWORD bind_speed = BINDSPEED_INDEFINITE;
418 BIND_OPTS bind_opts;
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;
424 return bind_speed;
427 /******************************************************************************
428 * ItemMoniker_BindToObject
429 ******************************************************************************/
430 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
431 IBindCtx* pbc,
432 IMoniker* pmkToLeft,
433 REFIID riid,
434 VOID** ppvResult)
436 ItemMonikerImpl *This = impl_from_IMoniker(iface);
437 IOleItemContainer *container;
438 HRESULT hr;
440 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
442 if(ppvResult ==NULL)
443 return E_POINTER;
445 if(pmkToLeft==NULL)
446 return E_INVALIDARG;
448 *ppvResult=0;
450 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
451 if (SUCCEEDED(hr))
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,
457 riid, ppvResult);
458 IOleItemContainer_Release(container);
461 return hr;
464 /******************************************************************************
465 * ItemMoniker_BindToStorage
466 ******************************************************************************/
467 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid,
468 void **ppvResult)
470 ItemMonikerImpl *moniker = impl_from_IMoniker(iface);
471 IOleItemContainer *container;
472 HRESULT hr;
474 TRACE("%p, %p, %p, %s, %p.\n", iface, pbc, pmkToLeft, debugstr_guid(riid), ppvResult);
476 *ppvResult = 0;
478 if (!pmkToLeft)
479 return E_INVALIDARG;
481 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
482 if (SUCCEEDED(hr))
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);
491 return hr;
494 /******************************************************************************
495 * ItemMoniker_Reduce
496 ******************************************************************************/
497 static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
498 IBindCtx* pbc,
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)
506 return E_POINTER;
508 ItemMonikerImpl_AddRef(iface);
510 *ppmkReduced=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)
518 DWORD order;
520 TRACE("%p, %p, %d, %p\n", iface, right, only_if_not_generic, result);
522 if (!result || !right)
523 return E_POINTER;
525 *result = NULL;
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 /******************************************************************************
534 * ItemMoniker_Enum
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)
541 return E_POINTER;
543 *ppenumMoniker = NULL;
545 return S_OK;
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);
557 if (!other)
558 return E_INVALIDARG;
560 other_moniker = unsafe_impl_from_IMoniker(other);
561 if (!other_moniker)
562 return S_FALSE;
564 return !wcsicmp(moniker->itemName, other_moniker->itemName) ? S_OK : S_FALSE;
567 /******************************************************************************
568 * ItemMoniker_Hash
569 ******************************************************************************/
570 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
572 ItemMonikerImpl *This = impl_from_IMoniker(iface);
573 DWORD h = 0;
574 int i,len;
575 int off = 0;
576 LPOLESTR val;
578 if (pdwHash==NULL)
579 return E_POINTER;
581 val = This->itemName;
582 len = lstrlenW(val);
584 for (i = len ; i > 0; i--)
585 h = (h * 3) ^ towupper(val[off++]);
587 *pdwHash=h;
589 return S_OK;
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;
601 HRESULT hr;
603 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
605 if (!pbc)
606 return E_INVALIDARG;
608 if (!pmkToLeft)
610 if (pmkNewlyRunning)
612 return IMoniker_IsEqual(iface, pmkNewlyRunning);
614 else
616 hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
617 if (SUCCEEDED(hr))
619 hr = IRunningObjectTable_IsRunning(rot, iface);
620 IRunningObjectTable_Release(rot);
624 else
626 /* Container itself must be running too. */
627 hr = IMoniker_IsRunning(pmkToLeft, pbc, NULL, NULL);
628 if (hr != S_OK)
629 return hr;
631 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
632 if (SUCCEEDED(hr))
634 hr = IOleItemContainer_IsRunning(container, moniker->itemName);
635 IOleItemContainer_Release(container);
639 return hr;
642 /******************************************************************************
643 * ItemMoniker_GetTimeOfLastChange
644 ******************************************************************************/
645 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
646 IBindCtx* pbc,
647 IMoniker* pmkToLeft,
648 FILETIME* pItemTime)
650 IRunningObjectTable* rot;
651 HRESULT res;
652 IMoniker *compositeMk;
654 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
656 if (pItemTime==NULL)
657 return E_INVALIDARG;
659 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
660 if (pmkToLeft==NULL)
662 return MK_E_NOTBINDABLE;
663 else {
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);
670 if (FAILED(res))
671 return res;
673 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
674 if (FAILED(res)) {
675 IMoniker_Release(compositeMk);
676 return res;
679 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
681 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
683 IMoniker_Release(compositeMk);
686 return res;
689 /******************************************************************************
690 * ItemMoniker_Inverse
691 ******************************************************************************/
692 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
694 TRACE("(%p,%p)\n",iface,ppmk);
696 if (ppmk==NULL)
697 return E_POINTER;
699 return CreateAntiMoniker(ppmk);
702 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other,
703 IMoniker **prefix)
705 TRACE("%p, %p, %p\n", iface, other, prefix);
707 if (IMoniker_IsEqual(iface, other) == S_OK)
709 *prefix = iface;
710 IMoniker_AddRef(iface);
711 return MK_S_US;
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)
722 return E_INVALIDARG;
724 *result = NULL;
726 return MK_E_NOTBINDABLE;
729 /******************************************************************************
730 * ItemMoniker_GetDisplayName
731 ******************************************************************************/
732 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
733 IBindCtx* pbc,
734 IMoniker* pmkToLeft,
735 LPOLESTR *ppszDisplayName)
737 ItemMonikerImpl *This = impl_from_IMoniker(iface);
738 SIZE_T size;
740 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
742 if (ppszDisplayName==NULL)
743 return E_POINTER;
745 if (pmkToLeft!=NULL){
746 return E_INVALIDARG;
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));
765 return S_OK;
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;
777 HRESULT hr;
779 TRACE("%p, %p, %p, %s, %p, %p.\n", iface, pbc, pmkToLeft, debugstr_w(displayname), eaten, ppmkOut);
781 if (!pmkToLeft)
782 return MK_E_SYNTAX;
784 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
785 if (SUCCEEDED(hr))
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);
791 if (SUCCEEDED(hr))
793 hr = IParseDisplayName_ParseDisplayName(parser, pbc, displayname, eaten, ppmkOut);
794 IParseDisplayName_Release(parser);
797 IOleItemContainer_Release(container);
800 return hr;
803 /******************************************************************************
804 * ItemMoniker_IsSystemMoniker
805 ******************************************************************************/
806 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
808 TRACE("(%p,%p)\n",iface,pwdMksys);
810 if (!pwdMksys)
811 return E_POINTER;
813 (*pwdMksys)=MKSYS_ITEMMONIKER;
815 return S_OK;
818 /*******************************************************************************
819 * ItemMonikerIROTData_QueryInterface
820 *******************************************************************************/
821 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
822 void **ppvObject)
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,
860 ULONG *data_len)
862 ItemMonikerImpl *This = impl_from_IROTData(iface);
863 int name_len = lstrlenW(This->itemName);
864 int delim_len, i;
865 WCHAR *ptrW;
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;
874 /* write CLSID */
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));
883 /* write name */
884 for (i = 0, ptrW = (WCHAR *)buffer; i < name_len; ++i)
885 ptrW[i] = towupper(This->itemName[i]);
886 ptrW[i] = 0;
888 return S_OK;
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)
924 return NULL;
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;
944 int str_len;
945 HRESULT hr;
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;
954 moniker->ref = 1;
956 str_len = (lstrlenW(name) + 1) * sizeof(WCHAR);
957 moniker->itemName = heap_alloc(str_len);
958 if (!moniker->itemName)
960 hr = E_OUTOFMEMORY;
961 goto failed;
963 memcpy(moniker->itemName, name, str_len);
965 if (delimiter)
967 str_len = (lstrlenW(delimiter) + 1) * sizeof(WCHAR);
968 moniker->itemDelimiter = heap_alloc(str_len);
969 if (!moniker->itemDelimiter)
971 hr = E_OUTOFMEMORY;
972 goto failed;
974 memcpy(moniker->itemDelimiter, delimiter, str_len);
977 *ret = &moniker->IMoniker_iface;
979 return S_OK;
981 failed:
982 IMoniker_Release(&moniker->IMoniker_iface);
984 return hr;
987 HRESULT WINAPI ItemMoniker_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
989 IMoniker *moniker;
990 HRESULT hr;
992 TRACE("(%p, %s, %p)\n", outer, debugstr_guid(riid), ppv);
994 *ppv = NULL;
996 if (outer)
997 return CLASS_E_NOAGGREGATION;
999 if (FAILED(hr = CreateItemMoniker(L"", L"", &moniker)))
1000 return hr;
1002 hr = IMoniker_QueryInterface(moniker, riid, ppv);
1003 IMoniker_Release(moniker);
1005 return hr;