d3d9/tests: Use CRT allocation functions.
[wine.git] / dlls / ole32 / itemmoniker.c
blob3e4edc0bb91318e7e6c5f106cc5e76cc5b9fefe0
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 #include "winerror.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "wine/debug.h"
32 #include "ole2.h"
33 #include "moniker.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.*/
41 LONG ref;
42 LPOLESTR itemName; /* item name identified by this ItemMoniker */
43 LPOLESTR itemDelimiter; /* Delimiter string */
44 IUnknown *pMarshal; /* custom marshaler */
45 } ItemMonikerImpl;
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);
59 struct container_lock
61 IUnknown IUnknown_iface;
62 LONG refcount;
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))
75 *obj = iface;
76 IUnknown_AddRef(iface);
77 return S_OK;
80 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
81 *obj = NULL;
82 return E_NOINTERFACE;
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);
96 if (!refcount)
98 IOleItemContainer_LockContainer(lock->container, FALSE);
99 IOleItemContainer_Release(lock->container);
100 free(lock);
103 return refcount;
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;
116 HRESULT hr;
118 if (!(lock = malloc(sizeof(*lock))))
119 return E_OUTOFMEMORY;
121 if (FAILED(hr = IOleItemContainer_LockContainer(container, TRUE)))
123 free(lock);
124 return hr;
127 lock->IUnknown_iface.lpVtbl = &container_lock_vtbl;
128 lock->refcount = 1;
129 lock->container = container;
130 IOleItemContainer_AddRef(lock->container);
132 hr = IBindCtx_RegisterObjectBound(pbc, &lock->IUnknown_iface);
133 IUnknown_Release(&lock->IUnknown_iface);
134 return hr;
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);
146 if (!ppvObject)
147 return E_INVALIDARG;
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))
155 *ppvObject = iface;
157 else if (IsEqualIID(&IID_IROTData, riid))
158 *ppvObject = &This->IROTData_iface;
159 else if (IsEqualIID(&IID_IMarshal, riid))
161 HRESULT hr = S_OK;
162 if (!This->pMarshal)
163 hr = MonikerMarshal_Create(iface, &This->pMarshal);
164 if (hr != S_OK)
165 return hr;
166 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
168 else
170 *ppvObject = NULL;
171 return E_NOINTERFACE;
174 IMoniker_AddRef(iface);
175 return S_OK;
178 /******************************************************************************
179 * ItemMoniker_AddRef
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);
200 if (!refcount)
202 if (moniker->pMarshal) IUnknown_Release(moniker->pMarshal);
203 free(moniker->itemName);
204 free(moniker->itemDelimiter);
205 free(moniker);
208 return refcount;
211 /******************************************************************************
212 * ItemMoniker_GetClassID
213 ******************************************************************************/
214 static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
216 TRACE("(%p,%p)\n",iface,pClassID);
218 if (pClassID==NULL)
219 return E_POINTER;
221 *pClassID = CLSID_ItemMoniker;
223 return S_OK;
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);
237 return S_FALSE;
240 static HRESULT item_moniker_load_string_record(IStream *stream, WCHAR **ret)
242 DWORD str_len, read_len, lenW, i;
243 HRESULT hr = S_OK;
244 char *buffer;
245 WCHAR *str;
247 IStream_Read(stream, &str_len, sizeof(str_len), &read_len);
248 if (read_len != sizeof(str_len))
249 return E_FAIL;
251 if (!str_len)
253 free(*ret);
254 *ret = NULL;
255 return S_OK;
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)
264 free(buffer);
265 return E_FAIL;
268 /* Skip ansi buffer, it must be null terminated. */
269 i = 0;
270 while (i < str_len && buffer[i])
271 i++;
273 if (buffer[i])
275 WARN("Expected null terminated ansi name.\n");
276 hr = E_FAIL;
277 goto end;
280 if (i < str_len - 1)
282 str_len -= i + 1;
284 if (str_len % sizeof(WCHAR))
286 WARN("Unexpected Unicode name length %ld.\n", str_len);
287 hr = E_FAIL;
288 goto end;
291 str = malloc(str_len + sizeof(WCHAR));
292 if (str)
294 memcpy(str, &buffer[i + 1], str_len);
295 str[str_len / sizeof(WCHAR)] = 0;
298 else
300 lenW = MultiByteToWideChar(CP_ACP, 0, buffer, -1, NULL, 0);
301 str = malloc(lenW * sizeof(WCHAR));
302 if (str)
303 MultiByteToWideChar(CP_ACP, 0, buffer, -1, str, lenW);
306 if (str)
308 free(*ret);
309 *ret = str;
311 else
312 hr = E_OUTOFMEMORY;
314 end:
315 free(buffer);
317 return hr;
320 /******************************************************************************
321 * ItemMoniker_Load
322 ******************************************************************************/
323 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker *iface, IStream *stream)
325 ItemMonikerImpl *This = impl_from_IMoniker(iface);
326 HRESULT hr;
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);
336 if (SUCCEEDED(hr))
337 hr = item_moniker_load_string_record(stream, &This->itemName);
339 return hr;
342 /******************************************************************************
343 * ItemMoniker_Save
344 ******************************************************************************/
345 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker *iface, IStream *stream, BOOL fClearDirty)
347 ItemMonikerImpl *This = impl_from_IMoniker(iface);
348 int str_len;
349 HRESULT hr;
350 char *str;
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);
367 free(str);
369 else
371 str_len = 0;
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);
380 free(str);
382 return hr;
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);
395 if (!pcbSize)
396 return E_POINTER;
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;
409 return S_OK;
412 static DWORD get_bind_speed_from_bindctx(IBindCtx *pbc)
414 DWORD bind_speed = BINDSPEED_INDEFINITE;
415 BIND_OPTS bind_opts;
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;
421 return bind_speed;
424 /******************************************************************************
425 * ItemMoniker_BindToObject
426 ******************************************************************************/
427 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
428 IBindCtx* pbc,
429 IMoniker* pmkToLeft,
430 REFIID riid,
431 VOID** ppvResult)
433 ItemMonikerImpl *This = impl_from_IMoniker(iface);
434 IOleItemContainer *container;
435 HRESULT hr;
437 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
439 if(ppvResult ==NULL)
440 return E_POINTER;
442 if(pmkToLeft==NULL)
443 return E_INVALIDARG;
445 *ppvResult=0;
447 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
448 if (SUCCEEDED(hr))
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,
454 riid, ppvResult);
455 IOleItemContainer_Release(container);
458 return hr;
461 /******************************************************************************
462 * ItemMoniker_BindToStorage
463 ******************************************************************************/
464 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid,
465 void **ppvResult)
467 ItemMonikerImpl *moniker = impl_from_IMoniker(iface);
468 IOleItemContainer *container;
469 HRESULT hr;
471 TRACE("%p, %p, %p, %s, %p.\n", iface, pbc, pmkToLeft, debugstr_guid(riid), ppvResult);
473 *ppvResult = 0;
475 if (!pmkToLeft)
476 return E_INVALIDARG;
478 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
479 if (SUCCEEDED(hr))
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);
488 return hr;
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)
497 return E_POINTER;
499 ItemMonikerImpl_AddRef(iface);
501 *ppmkReduced=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)
509 DWORD order;
511 TRACE("%p, %p, %d, %p\n", iface, right, only_if_not_generic, result);
513 if (!result || !right)
514 return E_POINTER;
516 *result = NULL;
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 /******************************************************************************
525 * ItemMoniker_Enum
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)
532 return E_POINTER;
534 *ppenumMoniker = NULL;
536 return S_OK;
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);
548 if (!other)
549 return E_INVALIDARG;
551 other_moniker = unsafe_impl_from_IMoniker(other);
552 if (!other_moniker)
553 return S_FALSE;
555 return !wcsicmp(moniker->itemName, other_moniker->itemName) ? S_OK : S_FALSE;
558 /******************************************************************************
559 * ItemMoniker_Hash
560 ******************************************************************************/
561 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
563 ItemMonikerImpl *This = impl_from_IMoniker(iface);
564 DWORD h = 0;
565 int i,len;
566 int off = 0;
567 LPOLESTR val;
569 if (pdwHash==NULL)
570 return E_POINTER;
572 val = This->itemName;
573 len = lstrlenW(val);
575 for (i = len ; i > 0; i--)
576 h = (h * 3) ^ towupper(val[off++]);
578 *pdwHash=h;
580 return S_OK;
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;
592 HRESULT hr;
594 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
596 if (!pbc)
597 return E_INVALIDARG;
599 if (!pmkToLeft)
601 if (pmkNewlyRunning)
603 return IMoniker_IsEqual(iface, pmkNewlyRunning);
605 else
607 hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
608 if (SUCCEEDED(hr))
610 hr = IRunningObjectTable_IsRunning(rot, iface);
611 IRunningObjectTable_Release(rot);
615 else
617 /* Container itself must be running too. */
618 hr = IMoniker_IsRunning(pmkToLeft, pbc, NULL, NULL);
619 if (hr != S_OK)
620 return hr;
622 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
623 if (SUCCEEDED(hr))
625 hr = IOleItemContainer_IsRunning(container, moniker->itemName);
626 IOleItemContainer_Release(container);
630 return hr;
633 /******************************************************************************
634 * ItemMoniker_GetTimeOfLastChange
635 ******************************************************************************/
636 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
637 IBindCtx* pbc,
638 IMoniker* pmkToLeft,
639 FILETIME* pItemTime)
641 IRunningObjectTable* rot;
642 HRESULT res;
643 IMoniker *compositeMk;
645 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
647 if (pItemTime==NULL)
648 return E_INVALIDARG;
650 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
651 if (pmkToLeft==NULL)
653 return MK_E_NOTBINDABLE;
654 else {
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);
661 if (FAILED(res))
662 return res;
664 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
665 if (FAILED(res)) {
666 IMoniker_Release(compositeMk);
667 return res;
670 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
672 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
674 IMoniker_Release(compositeMk);
677 return res;
680 /******************************************************************************
681 * ItemMoniker_Inverse
682 ******************************************************************************/
683 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
685 TRACE("(%p,%p)\n",iface,ppmk);
687 if (ppmk==NULL)
688 return E_POINTER;
690 return CreateAntiMoniker(ppmk);
693 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other,
694 IMoniker **prefix)
696 TRACE("%p, %p, %p\n", iface, other, prefix);
698 if (IMoniker_IsEqual(iface, other) == S_OK)
700 *prefix = iface;
701 IMoniker_AddRef(iface);
702 return MK_S_US;
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)
713 return E_INVALIDARG;
715 *result = NULL;
717 return MK_E_NOTBINDABLE;
720 /******************************************************************************
721 * ItemMoniker_GetDisplayName
722 ******************************************************************************/
723 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
724 IBindCtx* pbc,
725 IMoniker* pmkToLeft,
726 LPOLESTR *ppszDisplayName)
728 ItemMonikerImpl *This = impl_from_IMoniker(iface);
729 SIZE_T size;
731 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
733 if (ppszDisplayName==NULL)
734 return E_POINTER;
736 if (pmkToLeft!=NULL){
737 return E_INVALIDARG;
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));
756 return S_OK;
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;
768 HRESULT hr;
770 TRACE("%p, %p, %p, %s, %p, %p.\n", iface, pbc, pmkToLeft, debugstr_w(displayname), eaten, ppmkOut);
772 if (!pmkToLeft)
773 return MK_E_SYNTAX;
775 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
776 if (SUCCEEDED(hr))
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);
782 if (SUCCEEDED(hr))
784 hr = IParseDisplayName_ParseDisplayName(parser, pbc, displayname, eaten, ppmkOut);
785 IParseDisplayName_Release(parser);
788 IOleItemContainer_Release(container);
791 return hr;
794 /******************************************************************************
795 * ItemMoniker_IsSystemMoniker
796 ******************************************************************************/
797 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
799 TRACE("(%p,%p)\n",iface,pwdMksys);
801 if (!pwdMksys)
802 return E_POINTER;
804 (*pwdMksys)=MKSYS_ITEMMONIKER;
806 return S_OK;
809 /*******************************************************************************
810 * ItemMonikerIROTData_QueryInterface
811 *******************************************************************************/
812 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
813 void **ppvObject)
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,
851 ULONG *data_len)
853 ItemMonikerImpl *This = impl_from_IROTData(iface);
854 int name_len = lstrlenW(This->itemName);
855 int delim_len, i;
856 WCHAR *ptrW;
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;
865 /* write CLSID */
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));
874 /* write name */
875 for (i = 0, ptrW = (WCHAR *)buffer; i < name_len; ++i)
876 ptrW[i] = towupper(This->itemName[i]);
877 ptrW[i] = 0;
879 return S_OK;
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)
915 return NULL;
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;
935 int str_len;
936 HRESULT hr;
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;
945 moniker->ref = 1;
947 str_len = (lstrlenW(name) + 1) * sizeof(WCHAR);
948 moniker->itemName = malloc(str_len);
949 if (!moniker->itemName)
951 hr = E_OUTOFMEMORY;
952 goto failed;
954 memcpy(moniker->itemName, name, str_len);
956 if (delimiter)
958 str_len = (lstrlenW(delimiter) + 1) * sizeof(WCHAR);
959 moniker->itemDelimiter = malloc(str_len);
960 if (!moniker->itemDelimiter)
962 hr = E_OUTOFMEMORY;
963 goto failed;
965 memcpy(moniker->itemDelimiter, delimiter, str_len);
968 *ret = &moniker->IMoniker_iface;
970 return S_OK;
972 failed:
973 IMoniker_Release(&moniker->IMoniker_iface);
975 return hr;
978 HRESULT WINAPI ItemMoniker_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
980 IMoniker *moniker;
981 HRESULT hr;
983 TRACE("(%p, %s, %p)\n", outer, debugstr_guid(riid), ppv);
985 *ppv = NULL;
987 if (outer)
988 return CLASS_E_NOAGGREGATION;
990 if (FAILED(hr = CreateItemMoniker(L"", L"", &moniker)))
991 return hr;
993 hr = IMoniker_QueryInterface(moniker, riid, ppv);
994 IMoniker_Release(moniker);
996 return hr;