evr: Add a forward for MFGetStrideForBitmapInfoHeader().
[wine.git] / dlls / ole32 / itemmoniker.c
blob786d183d59847538dd1ed4854a2a4854bb7d42b0
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;
514 /******************************************************************************
515 * ItemMoniker_ComposeWith
516 ******************************************************************************/
517 static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
518 IMoniker* pmkRight,
519 BOOL fOnlyIfNotGeneric,
520 IMoniker** ppmkComposite)
522 HRESULT res=S_OK;
523 DWORD mkSys,mkSys2, order;
524 IEnumMoniker* penumMk=0;
525 IMoniker *pmostLeftMk=0;
526 IMoniker* tempMkComposite=0;
528 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
530 if ((ppmkComposite==NULL)||(pmkRight==NULL))
531 return E_POINTER;
533 *ppmkComposite=0;
535 if (is_anti_moniker(pmkRight, &order))
537 return order > 1 ? create_anti_moniker(order - 1, ppmkComposite) : S_OK;
539 else
540 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
541 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
542 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
543 if(mkSys==MKSYS_GENERICCOMPOSITE){
545 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
547 if (FAILED(res))
548 return res;
550 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
552 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
554 if(mkSys2==MKSYS_ANTIMONIKER){
556 IMoniker_Release(pmostLeftMk);
558 tempMkComposite=iface;
559 IMoniker_AddRef(iface);
561 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
563 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
565 IMoniker_Release(tempMkComposite);
566 IMoniker_Release(pmostLeftMk);
568 tempMkComposite=*ppmkComposite;
569 IMoniker_AddRef(tempMkComposite);
571 return res;
573 else
574 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
576 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
577 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
578 a NULL moniker and a return value of MK_E_NEEDGENERIC */
579 else
580 if (!fOnlyIfNotGeneric)
581 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
583 else
584 return MK_E_NEEDGENERIC;
587 /******************************************************************************
588 * ItemMoniker_Enum
589 ******************************************************************************/
590 static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
592 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
594 if (ppenumMoniker == NULL)
595 return E_POINTER;
597 *ppenumMoniker = NULL;
599 return S_OK;
602 /******************************************************************************
603 * ItemMoniker_IsEqual
604 ******************************************************************************/
605 static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker *iface, IMoniker *other)
607 ItemMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
609 TRACE("%p, %p.\n", iface, other);
611 if (!other)
612 return E_INVALIDARG;
614 other_moniker = unsafe_impl_from_IMoniker(other);
615 if (!other_moniker)
616 return S_FALSE;
618 return !wcsicmp(moniker->itemName, other_moniker->itemName) ? S_OK : S_FALSE;
621 /******************************************************************************
622 * ItemMoniker_Hash
623 ******************************************************************************/
624 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
626 ItemMonikerImpl *This = impl_from_IMoniker(iface);
627 DWORD h = 0;
628 int i,len;
629 int off = 0;
630 LPOLESTR val;
632 if (pdwHash==NULL)
633 return E_POINTER;
635 val = This->itemName;
636 len = lstrlenW(val);
638 for (i = len ; i > 0; i--)
639 h = (h * 3) ^ towupper(val[off++]);
641 *pdwHash=h;
643 return S_OK;
646 /******************************************************************************
647 * ItemMoniker_IsRunning
648 ******************************************************************************/
649 static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
650 IMoniker *pmkNewlyRunning)
652 ItemMonikerImpl *moniker = impl_from_IMoniker(iface);
653 IOleItemContainer *container;
654 IRunningObjectTable* rot;
655 HRESULT hr;
657 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
659 if (!pbc)
660 return E_INVALIDARG;
662 if (!pmkToLeft)
664 if (pmkNewlyRunning)
666 return IMoniker_IsEqual(iface, pmkNewlyRunning);
668 else
670 hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
671 if (SUCCEEDED(hr))
673 hr = IRunningObjectTable_IsRunning(rot, iface);
674 IRunningObjectTable_Release(rot);
678 else
680 /* Container itself must be running too. */
681 hr = IMoniker_IsRunning(pmkToLeft, pbc, NULL, NULL);
682 if (hr != S_OK)
683 return hr;
685 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
686 if (SUCCEEDED(hr))
688 hr = IOleItemContainer_IsRunning(container, moniker->itemName);
689 IOleItemContainer_Release(container);
693 return hr;
696 /******************************************************************************
697 * ItemMoniker_GetTimeOfLastChange
698 ******************************************************************************/
699 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
700 IBindCtx* pbc,
701 IMoniker* pmkToLeft,
702 FILETIME* pItemTime)
704 IRunningObjectTable* rot;
705 HRESULT res;
706 IMoniker *compositeMk;
708 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
710 if (pItemTime==NULL)
711 return E_INVALIDARG;
713 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
714 if (pmkToLeft==NULL)
716 return MK_E_NOTBINDABLE;
717 else {
719 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
720 /* the time of last change. If the object is not in the ROT, the method calls */
721 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
723 res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
724 if (FAILED(res))
725 return res;
727 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
728 if (FAILED(res)) {
729 IMoniker_Release(compositeMk);
730 return res;
733 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
735 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
737 IMoniker_Release(compositeMk);
740 return res;
743 /******************************************************************************
744 * ItemMoniker_Inverse
745 ******************************************************************************/
746 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
748 TRACE("(%p,%p)\n",iface,ppmk);
750 if (ppmk==NULL)
751 return E_POINTER;
753 return CreateAntiMoniker(ppmk);
756 /******************************************************************************
757 * ItemMoniker_CommonPrefixWith
758 ******************************************************************************/
759 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
761 DWORD mkSys;
763 TRACE("(%p,%p)\n", pmkOther, ppmkPrefix);
765 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
766 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
767 /* to this moniker and returns MK_S_US */
769 if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
771 *ppmkPrefix=iface;
773 IMoniker_AddRef(iface);
775 return MK_S_US;
777 else
778 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
779 /* the case where the other moniker is a generic composite. */
780 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
783 /******************************************************************************
784 * ItemMoniker_RelativePathTo
785 ******************************************************************************/
786 static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
788 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
790 if (ppmkRelPath==NULL)
791 return E_POINTER;
793 *ppmkRelPath=0;
795 return MK_E_NOTBINDABLE;
798 /******************************************************************************
799 * ItemMoniker_GetDisplayName
800 ******************************************************************************/
801 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
802 IBindCtx* pbc,
803 IMoniker* pmkToLeft,
804 LPOLESTR *ppszDisplayName)
806 ItemMonikerImpl *This = impl_from_IMoniker(iface);
807 SIZE_T size;
809 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
811 if (ppszDisplayName==NULL)
812 return E_POINTER;
814 if (pmkToLeft!=NULL){
815 return E_INVALIDARG;
818 size = lstrlenW(This->itemName) + 1;
819 if (This->itemDelimiter)
820 size += lstrlenW(This->itemDelimiter);
821 size *= sizeof(WCHAR);
823 *ppszDisplayName = CoTaskMemAlloc(size);
824 if (*ppszDisplayName==NULL)
825 return E_OUTOFMEMORY;
827 (*ppszDisplayName)[0] = 0;
828 if (This->itemDelimiter)
829 lstrcatW(*ppszDisplayName, This->itemDelimiter);
830 lstrcatW(*ppszDisplayName,This->itemName);
832 TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
834 return S_OK;
837 /******************************************************************************
838 * ItemMoniker_ParseDisplayName
839 ******************************************************************************/
840 static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
841 LPOLESTR displayname, ULONG *eaten, IMoniker **ppmkOut)
843 ItemMonikerImpl *This = impl_from_IMoniker(iface);
844 IOleItemContainer *container;
845 IParseDisplayName *parser;
846 HRESULT hr;
848 TRACE("%p, %p, %p, %s, %p, %p.\n", iface, pbc, pmkToLeft, debugstr_w(displayname), eaten, ppmkOut);
850 if (!pmkToLeft)
851 return MK_E_SYNTAX;
853 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
854 if (SUCCEEDED(hr))
856 if (SUCCEEDED(hr = set_container_lock(container, pbc)))
858 hr = IOleItemContainer_GetObject(container, This->itemName, get_bind_speed_from_bindctx(pbc), pbc,
859 &IID_IParseDisplayName, (void **)&parser);
860 if (SUCCEEDED(hr))
862 hr = IParseDisplayName_ParseDisplayName(parser, pbc, displayname, eaten, ppmkOut);
863 IParseDisplayName_Release(parser);
866 IOleItemContainer_Release(container);
869 return hr;
872 /******************************************************************************
873 * ItemMoniker_IsSystemMoniker
874 ******************************************************************************/
875 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
877 TRACE("(%p,%p)\n",iface,pwdMksys);
879 if (!pwdMksys)
880 return E_POINTER;
882 (*pwdMksys)=MKSYS_ITEMMONIKER;
884 return S_OK;
887 /*******************************************************************************
888 * ItemMonikerIROTData_QueryInterface
889 *******************************************************************************/
890 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
891 void **ppvObject)
894 ItemMonikerImpl *This = impl_from_IROTData(iface);
896 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject);
898 return ItemMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
901 /***********************************************************************
902 * ItemMonikerIROTData_AddRef
904 static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
906 ItemMonikerImpl *This = impl_from_IROTData(iface);
908 TRACE("(%p)\n",iface);
910 return ItemMonikerImpl_AddRef(&This->IMoniker_iface);
913 /***********************************************************************
914 * ItemMonikerIROTData_Release
916 static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
918 ItemMonikerImpl *This = impl_from_IROTData(iface);
920 TRACE("(%p)\n",iface);
922 return ItemMonikerImpl_Release(&This->IMoniker_iface);
925 /******************************************************************************
926 * ItemMonikerIROTData_GetComparisonData
927 ******************************************************************************/
928 static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData *iface, BYTE *buffer, ULONG max_len,
929 ULONG *data_len)
931 ItemMonikerImpl *This = impl_from_IROTData(iface);
932 int name_len = lstrlenW(This->itemName);
933 int delim_len, i;
934 WCHAR *ptrW;
936 TRACE("(%p, %p, %u, %p)\n", iface, buffer, max_len, data_len);
938 delim_len = This->itemDelimiter && This->itemDelimiter[0] ? lstrlenW(This->itemDelimiter) : 0;
939 *data_len = sizeof(CLSID) + sizeof(WCHAR) + (delim_len + name_len) * sizeof(WCHAR);
940 if (max_len < *data_len)
941 return E_OUTOFMEMORY;
943 /* write CLSID */
944 memcpy(buffer, &CLSID_ItemMoniker, sizeof(CLSID));
945 buffer += sizeof(CLSID);
947 /* write delimiter */
948 for (i = 0, ptrW = (WCHAR *)buffer; i < delim_len; ++i)
949 ptrW[i] = towupper(This->itemDelimiter[i]);
950 buffer += (delim_len * sizeof(WCHAR));
952 /* write name */
953 for (i = 0, ptrW = (WCHAR *)buffer; i < name_len; ++i)
954 ptrW[i] = towupper(This->itemName[i]);
955 ptrW[i] = 0;
957 return S_OK;
960 /********************************************************************************/
961 /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/
962 /* IPersistStream and IMoniker functions. */
963 static const IMonikerVtbl VT_ItemMonikerImpl =
965 ItemMonikerImpl_QueryInterface,
966 ItemMonikerImpl_AddRef,
967 ItemMonikerImpl_Release,
968 ItemMonikerImpl_GetClassID,
969 ItemMonikerImpl_IsDirty,
970 ItemMonikerImpl_Load,
971 ItemMonikerImpl_Save,
972 ItemMonikerImpl_GetSizeMax,
973 ItemMonikerImpl_BindToObject,
974 ItemMonikerImpl_BindToStorage,
975 ItemMonikerImpl_Reduce,
976 ItemMonikerImpl_ComposeWith,
977 ItemMonikerImpl_Enum,
978 ItemMonikerImpl_IsEqual,
979 ItemMonikerImpl_Hash,
980 ItemMonikerImpl_IsRunning,
981 ItemMonikerImpl_GetTimeOfLastChange,
982 ItemMonikerImpl_Inverse,
983 ItemMonikerImpl_CommonPrefixWith,
984 ItemMonikerImpl_RelativePathTo,
985 ItemMonikerImpl_GetDisplayName,
986 ItemMonikerImpl_ParseDisplayName,
987 ItemMonikerImpl_IsSystemMoniker
990 static ItemMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface)
992 if (iface->lpVtbl != &VT_ItemMonikerImpl)
993 return NULL;
994 return CONTAINING_RECORD(iface, ItemMonikerImpl, IMoniker_iface);
997 /********************************************************************************/
998 /* Virtual function table for the IROTData class. */
999 static const IROTDataVtbl VT_ROTDataImpl =
1001 ItemMonikerROTDataImpl_QueryInterface,
1002 ItemMonikerROTDataImpl_AddRef,
1003 ItemMonikerROTDataImpl_Release,
1004 ItemMonikerROTDataImpl_GetComparisonData
1007 /******************************************************************************
1008 * CreateItemMoniker [OLE32.@]
1009 ******************************************************************************/
1010 HRESULT WINAPI CreateItemMoniker(const WCHAR *delimiter, const WCHAR *name, IMoniker **ret)
1012 ItemMonikerImpl *moniker;
1013 int str_len;
1014 HRESULT hr;
1016 TRACE("%s, %s, %p.\n", debugstr_w(delimiter), debugstr_w(name), ret);
1018 if (!(moniker = heap_alloc_zero(sizeof(*moniker))))
1019 return E_OUTOFMEMORY;
1021 moniker->IMoniker_iface.lpVtbl = &VT_ItemMonikerImpl;
1022 moniker->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
1023 moniker->ref = 1;
1025 str_len = (lstrlenW(name) + 1) * sizeof(WCHAR);
1026 moniker->itemName = heap_alloc(str_len);
1027 if (!moniker->itemName)
1029 hr = E_OUTOFMEMORY;
1030 goto failed;
1032 memcpy(moniker->itemName, name, str_len);
1034 if (delimiter)
1036 str_len = (lstrlenW(delimiter) + 1) * sizeof(WCHAR);
1037 moniker->itemDelimiter = heap_alloc(str_len);
1038 if (!moniker->itemDelimiter)
1040 hr = E_OUTOFMEMORY;
1041 goto failed;
1043 memcpy(moniker->itemDelimiter, delimiter, str_len);
1046 *ret = &moniker->IMoniker_iface;
1048 return S_OK;
1050 failed:
1051 IMoniker_Release(&moniker->IMoniker_iface);
1053 return hr;
1056 HRESULT WINAPI ItemMoniker_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1058 IMoniker *moniker;
1059 HRESULT hr;
1061 TRACE("(%p, %s, %p)\n", outer, debugstr_guid(riid), ppv);
1063 *ppv = NULL;
1065 if (outer)
1066 return CLASS_E_NOAGGREGATION;
1068 if (FAILED(hr = CreateItemMoniker(L"", L"", &moniker)))
1069 return hr;
1071 hr = IMoniker_QueryInterface(moniker, riid, ppv);
1072 IMoniker_Release(moniker);
1074 return hr;