dsdmo: Add Flanger effect stub.
[wine.git] / dlls / ole32 / itemmoniker.c
blobf0c722bbf26e9da6e1761bbb5f6ea8977d57fe65
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 "ole2.h"
35 #include "moniker.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.*/
43 LONG ref;
44 LPOLESTR itemName; /* item name identified by this ItemMoniker */
45 LPOLESTR itemDelimiter; /* Delimiter string */
46 IUnknown *pMarshal; /* custom marshaler */
47 } ItemMonikerImpl;
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);
61 struct container_lock
63 IUnknown IUnknown_iface;
64 LONG refcount;
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))
77 *obj = iface;
78 IUnknown_AddRef(iface);
79 return S_OK;
82 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
83 *obj = NULL;
84 return E_NOINTERFACE;
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);
98 if (!refcount)
100 IOleItemContainer_LockContainer(lock->container, FALSE);
101 IOleItemContainer_Release(lock->container);
102 free(lock);
105 return refcount;
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;
118 HRESULT hr;
120 if (!(lock = malloc(sizeof(*lock))))
121 return E_OUTOFMEMORY;
123 if (FAILED(hr = IOleItemContainer_LockContainer(container, TRUE)))
125 free(lock);
126 return hr;
129 lock->IUnknown_iface.lpVtbl = &container_lock_vtbl;
130 lock->refcount = 1;
131 lock->container = container;
132 IOleItemContainer_AddRef(lock->container);
134 hr = IBindCtx_RegisterObjectBound(pbc, &lock->IUnknown_iface);
135 IUnknown_Release(&lock->IUnknown_iface);
136 return hr;
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);
148 if (!ppvObject)
149 return E_INVALIDARG;
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))
157 *ppvObject = iface;
159 else if (IsEqualIID(&IID_IROTData, riid))
160 *ppvObject = &This->IROTData_iface;
161 else if (IsEqualIID(&IID_IMarshal, riid))
163 HRESULT hr = S_OK;
164 if (!This->pMarshal)
165 hr = MonikerMarshal_Create(iface, &This->pMarshal);
166 if (hr != S_OK)
167 return hr;
168 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
170 else
172 *ppvObject = NULL;
173 return E_NOINTERFACE;
176 IMoniker_AddRef(iface);
177 return S_OK;
180 /******************************************************************************
181 * ItemMoniker_AddRef
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);
202 if (!refcount)
204 if (moniker->pMarshal) IUnknown_Release(moniker->pMarshal);
205 free(moniker->itemName);
206 free(moniker->itemDelimiter);
207 free(moniker);
210 return refcount;
213 /******************************************************************************
214 * ItemMoniker_GetClassID
215 ******************************************************************************/
216 static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
218 TRACE("(%p,%p)\n",iface,pClassID);
220 if (pClassID==NULL)
221 return E_POINTER;
223 *pClassID = CLSID_ItemMoniker;
225 return S_OK;
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);
239 return S_FALSE;
242 static HRESULT item_moniker_load_string_record(IStream *stream, WCHAR **ret)
244 DWORD str_len, read_len, lenW, i;
245 HRESULT hr = S_OK;
246 char *buffer;
247 WCHAR *str;
249 IStream_Read(stream, &str_len, sizeof(str_len), &read_len);
250 if (read_len != sizeof(str_len))
251 return E_FAIL;
253 if (!str_len)
255 free(*ret);
256 *ret = NULL;
257 return S_OK;
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)
266 free(buffer);
267 return E_FAIL;
270 /* Skip ansi buffer, it must be null terminated. */
271 i = 0;
272 while (i < str_len && buffer[i])
273 i++;
275 if (buffer[i])
277 WARN("Expected null terminated ansi name.\n");
278 hr = E_FAIL;
279 goto end;
282 if (i < str_len - 1)
284 str_len -= i + 1;
286 if (str_len % sizeof(WCHAR))
288 WARN("Unexpected Unicode name length %ld.\n", str_len);
289 hr = E_FAIL;
290 goto end;
293 str = malloc(str_len + sizeof(WCHAR));
294 if (str)
296 memcpy(str, &buffer[i + 1], str_len);
297 str[str_len / sizeof(WCHAR)] = 0;
300 else
302 lenW = MultiByteToWideChar(CP_ACP, 0, buffer, -1, NULL, 0);
303 str = malloc(lenW * sizeof(WCHAR));
304 if (str)
305 MultiByteToWideChar(CP_ACP, 0, buffer, -1, str, lenW);
308 if (str)
310 free(*ret);
311 *ret = str;
313 else
314 hr = E_OUTOFMEMORY;
316 end:
317 free(buffer);
319 return hr;
322 /******************************************************************************
323 * ItemMoniker_Load
324 ******************************************************************************/
325 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker *iface, IStream *stream)
327 ItemMonikerImpl *This = impl_from_IMoniker(iface);
328 HRESULT hr;
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);
338 if (SUCCEEDED(hr))
339 hr = item_moniker_load_string_record(stream, &This->itemName);
341 return hr;
344 /******************************************************************************
345 * ItemMoniker_Save
346 ******************************************************************************/
347 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker *iface, IStream *stream, BOOL fClearDirty)
349 ItemMonikerImpl *This = impl_from_IMoniker(iface);
350 int str_len;
351 HRESULT hr;
352 char *str;
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);
369 free(str);
371 else
373 str_len = 0;
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);
382 free(str);
384 return hr;
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);
397 if (!pcbSize)
398 return E_POINTER;
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;
411 return S_OK;
414 static DWORD get_bind_speed_from_bindctx(IBindCtx *pbc)
416 DWORD bind_speed = BINDSPEED_INDEFINITE;
417 BIND_OPTS bind_opts;
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;
423 return bind_speed;
426 /******************************************************************************
427 * ItemMoniker_BindToObject
428 ******************************************************************************/
429 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
430 IBindCtx* pbc,
431 IMoniker* pmkToLeft,
432 REFIID riid,
433 VOID** ppvResult)
435 ItemMonikerImpl *This = impl_from_IMoniker(iface);
436 IOleItemContainer *container;
437 HRESULT hr;
439 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
441 if(ppvResult ==NULL)
442 return E_POINTER;
444 if(pmkToLeft==NULL)
445 return E_INVALIDARG;
447 *ppvResult=0;
449 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
450 if (SUCCEEDED(hr))
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,
456 riid, ppvResult);
457 IOleItemContainer_Release(container);
460 return hr;
463 /******************************************************************************
464 * ItemMoniker_BindToStorage
465 ******************************************************************************/
466 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid,
467 void **ppvResult)
469 ItemMonikerImpl *moniker = impl_from_IMoniker(iface);
470 IOleItemContainer *container;
471 HRESULT hr;
473 TRACE("%p, %p, %p, %s, %p.\n", iface, pbc, pmkToLeft, debugstr_guid(riid), ppvResult);
475 *ppvResult = 0;
477 if (!pmkToLeft)
478 return E_INVALIDARG;
480 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
481 if (SUCCEEDED(hr))
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);
490 return hr;
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)
499 return E_POINTER;
501 ItemMonikerImpl_AddRef(iface);
503 *ppmkReduced=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)
511 DWORD order;
513 TRACE("%p, %p, %d, %p\n", iface, right, only_if_not_generic, result);
515 if (!result || !right)
516 return E_POINTER;
518 *result = NULL;
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 /******************************************************************************
527 * ItemMoniker_Enum
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)
534 return E_POINTER;
536 *ppenumMoniker = NULL;
538 return S_OK;
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);
550 if (!other)
551 return E_INVALIDARG;
553 other_moniker = unsafe_impl_from_IMoniker(other);
554 if (!other_moniker)
555 return S_FALSE;
557 return !wcsicmp(moniker->itemName, other_moniker->itemName) ? S_OK : S_FALSE;
560 /******************************************************************************
561 * ItemMoniker_Hash
562 ******************************************************************************/
563 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
565 ItemMonikerImpl *This = impl_from_IMoniker(iface);
566 DWORD h = 0;
567 int i,len;
568 int off = 0;
569 LPOLESTR val;
571 if (pdwHash==NULL)
572 return E_POINTER;
574 val = This->itemName;
575 len = lstrlenW(val);
577 for (i = len ; i > 0; i--)
578 h = (h * 3) ^ towupper(val[off++]);
580 *pdwHash=h;
582 return S_OK;
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;
594 HRESULT hr;
596 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
598 if (!pbc)
599 return E_INVALIDARG;
601 if (!pmkToLeft)
603 if (pmkNewlyRunning)
605 return IMoniker_IsEqual(iface, pmkNewlyRunning);
607 else
609 hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
610 if (SUCCEEDED(hr))
612 hr = IRunningObjectTable_IsRunning(rot, iface);
613 IRunningObjectTable_Release(rot);
617 else
619 /* Container itself must be running too. */
620 hr = IMoniker_IsRunning(pmkToLeft, pbc, NULL, NULL);
621 if (hr != S_OK)
622 return hr;
624 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
625 if (SUCCEEDED(hr))
627 hr = IOleItemContainer_IsRunning(container, moniker->itemName);
628 IOleItemContainer_Release(container);
632 return hr;
635 /******************************************************************************
636 * ItemMoniker_GetTimeOfLastChange
637 ******************************************************************************/
638 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
639 IBindCtx* pbc,
640 IMoniker* pmkToLeft,
641 FILETIME* pItemTime)
643 IRunningObjectTable* rot;
644 HRESULT res;
645 IMoniker *compositeMk;
647 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
649 if (pItemTime==NULL)
650 return E_INVALIDARG;
652 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
653 if (pmkToLeft==NULL)
655 return MK_E_NOTBINDABLE;
656 else {
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);
663 if (FAILED(res))
664 return res;
666 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
667 if (FAILED(res)) {
668 IMoniker_Release(compositeMk);
669 return res;
672 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
674 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
676 IMoniker_Release(compositeMk);
679 return res;
682 /******************************************************************************
683 * ItemMoniker_Inverse
684 ******************************************************************************/
685 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
687 TRACE("(%p,%p)\n",iface,ppmk);
689 if (ppmk==NULL)
690 return E_POINTER;
692 return CreateAntiMoniker(ppmk);
695 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other,
696 IMoniker **prefix)
698 TRACE("%p, %p, %p\n", iface, other, prefix);
700 if (IMoniker_IsEqual(iface, other) == S_OK)
702 *prefix = iface;
703 IMoniker_AddRef(iface);
704 return MK_S_US;
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)
715 return E_INVALIDARG;
717 *result = NULL;
719 return MK_E_NOTBINDABLE;
722 /******************************************************************************
723 * ItemMoniker_GetDisplayName
724 ******************************************************************************/
725 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
726 IBindCtx* pbc,
727 IMoniker* pmkToLeft,
728 LPOLESTR *ppszDisplayName)
730 ItemMonikerImpl *This = impl_from_IMoniker(iface);
731 SIZE_T size;
733 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
735 if (ppszDisplayName==NULL)
736 return E_POINTER;
738 if (pmkToLeft!=NULL){
739 return E_INVALIDARG;
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));
758 return S_OK;
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;
770 HRESULT hr;
772 TRACE("%p, %p, %p, %s, %p, %p.\n", iface, pbc, pmkToLeft, debugstr_w(displayname), eaten, ppmkOut);
774 if (!pmkToLeft)
775 return MK_E_SYNTAX;
777 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
778 if (SUCCEEDED(hr))
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);
784 if (SUCCEEDED(hr))
786 hr = IParseDisplayName_ParseDisplayName(parser, pbc, displayname, eaten, ppmkOut);
787 IParseDisplayName_Release(parser);
790 IOleItemContainer_Release(container);
793 return hr;
796 /******************************************************************************
797 * ItemMoniker_IsSystemMoniker
798 ******************************************************************************/
799 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
801 TRACE("(%p,%p)\n",iface,pwdMksys);
803 if (!pwdMksys)
804 return E_POINTER;
806 (*pwdMksys)=MKSYS_ITEMMONIKER;
808 return S_OK;
811 /*******************************************************************************
812 * ItemMonikerIROTData_QueryInterface
813 *******************************************************************************/
814 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
815 void **ppvObject)
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,
853 ULONG *data_len)
855 ItemMonikerImpl *This = impl_from_IROTData(iface);
856 int name_len = lstrlenW(This->itemName);
857 int delim_len, i;
858 WCHAR *ptrW;
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;
867 /* write CLSID */
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));
876 /* write name */
877 for (i = 0, ptrW = (WCHAR *)buffer; i < name_len; ++i)
878 ptrW[i] = towupper(This->itemName[i]);
879 ptrW[i] = 0;
881 return S_OK;
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)
917 return NULL;
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;
937 int str_len;
938 HRESULT hr;
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;
947 moniker->ref = 1;
949 str_len = (lstrlenW(name) + 1) * sizeof(WCHAR);
950 moniker->itemName = malloc(str_len);
951 if (!moniker->itemName)
953 hr = E_OUTOFMEMORY;
954 goto failed;
956 memcpy(moniker->itemName, name, str_len);
958 if (delimiter)
960 str_len = (lstrlenW(delimiter) + 1) * sizeof(WCHAR);
961 moniker->itemDelimiter = malloc(str_len);
962 if (!moniker->itemDelimiter)
964 hr = E_OUTOFMEMORY;
965 goto failed;
967 memcpy(moniker->itemDelimiter, delimiter, str_len);
970 *ret = &moniker->IMoniker_iface;
972 return S_OK;
974 failed:
975 IMoniker_Release(&moniker->IMoniker_iface);
977 return hr;
980 HRESULT WINAPI ItemMoniker_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
982 IMoniker *moniker;
983 HRESULT hr;
985 TRACE("(%p, %s, %p)\n", outer, debugstr_guid(riid), ppv);
987 *ppv = NULL;
989 if (outer)
990 return CLASS_E_NOAGGREGATION;
992 if (FAILED(hr = CreateItemMoniker(L"", L"", &moniker)))
993 return hr;
995 hr = IMoniker_QueryInterface(moniker, riid, ppv);
996 IMoniker_Release(moniker);
998 return hr;