mshtml: Wine Gecko 1.5 release.
[wine/multimedia.git] / dlls / ole32 / itemmoniker.c
blob32f70436788674fda047a8d8f8b415412822b86c
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
27 #define NONAMELESSSTRUCT
29 #include "winerror.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "winnls.h"
34 #include "wine/debug.h"
35 #include "ole2.h"
36 #include "wine/unicode.h"
37 #include "moniker.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41 /* ItemMoniker data structure */
42 typedef struct ItemMonikerImpl{
43 IMoniker IMoniker_iface; /* VTable relative to the IMoniker interface.*/
44 IROTData IROTData_iface; /* VTable relative to the IROTData interface.*/
45 LONG ref;
46 LPOLESTR itemName; /* item name identified by this ItemMoniker */
47 LPOLESTR itemDelimiter; /* Delimiter string */
48 IUnknown *pMarshal; /* custom marshaler */
49 } ItemMonikerImpl;
51 static inline ItemMonikerImpl *impl_from_IMoniker(IMoniker *iface)
53 return CONTAINING_RECORD(iface, ItemMonikerImpl, IMoniker_iface);
56 static inline ItemMonikerImpl *impl_from_IROTData(IROTData *iface)
58 return CONTAINING_RECORD(iface, ItemMonikerImpl, IROTData_iface);
61 static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
63 /*******************************************************************************
64 * ItemMoniker_QueryInterface
65 *******************************************************************************/
66 static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
68 ItemMonikerImpl *This = impl_from_IMoniker(iface);
70 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
72 if (!ppvObject)
73 return E_INVALIDARG;
75 /* Compare the riid with the interface IDs implemented by this object.*/
76 if (IsEqualIID(&IID_IUnknown, riid) ||
77 IsEqualIID(&IID_IPersist, riid) ||
78 IsEqualIID(&IID_IPersistStream, riid) ||
79 IsEqualIID(&IID_IMoniker, riid))
80 *ppvObject = iface;
81 else if (IsEqualIID(&IID_IROTData, riid))
82 *ppvObject = &This->IROTData_iface;
83 else if (IsEqualIID(&IID_IMarshal, riid))
85 HRESULT hr = S_OK;
86 if (!This->pMarshal)
87 hr = MonikerMarshal_Create(iface, &This->pMarshal);
88 if (hr != S_OK)
89 return hr;
90 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
92 else
94 *ppvObject = NULL;
95 return E_NOINTERFACE;
98 IMoniker_AddRef(iface);
99 return S_OK;
102 /******************************************************************************
103 * ItemMoniker_AddRef
104 ******************************************************************************/
105 static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
107 ItemMonikerImpl *This = impl_from_IMoniker(iface);
109 TRACE("(%p)\n",This);
111 return InterlockedIncrement(&This->ref);
114 /******************************************************************************
115 * ItemMoniker_Release
116 ******************************************************************************/
117 static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
119 ItemMonikerImpl *This = impl_from_IMoniker(iface);
120 ULONG ref;
122 TRACE("(%p)\n",This);
124 ref = InterlockedDecrement(&This->ref);
126 /* destroy the object if there's no more reference on it */
127 if (ref == 0) ItemMonikerImpl_Destroy(This);
129 return ref;
132 /******************************************************************************
133 * ItemMoniker_GetClassID
134 ******************************************************************************/
135 static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
137 TRACE("(%p,%p)\n",iface,pClassID);
139 if (pClassID==NULL)
140 return E_POINTER;
142 *pClassID = CLSID_ItemMoniker;
144 return S_OK;
147 /******************************************************************************
148 * ItemMoniker_IsDirty
149 ******************************************************************************/
150 static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
152 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
153 method in the OLE-provided moniker interfaces always return S_FALSE because
154 their internal state never changes. */
156 TRACE("(%p)\n",iface);
158 return S_FALSE;
161 /******************************************************************************
162 * ItemMoniker_Load
163 ******************************************************************************/
164 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
166 ItemMonikerImpl *This = impl_from_IMoniker(iface);
167 HRESULT res;
168 DWORD delimiterLength,nameLength,lenW;
169 CHAR *itemNameA,*itemDelimiterA;
170 ULONG bread;
172 TRACE("\n");
174 /* for more details about data read by this function see comments of ItemMonikerImpl_Save function */
176 /* read item delimiter string length + 1 */
177 res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);
178 if (bread != sizeof(DWORD))
179 return E_FAIL;
181 /* read item delimiter string */
182 if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength)))
183 return E_OUTOFMEMORY;
184 res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
185 if (bread != delimiterLength)
187 HeapFree( GetProcessHeap(), 0, itemDelimiterA );
188 return E_FAIL;
191 lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 );
192 This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR));
193 if (!This->itemDelimiter)
195 HeapFree( GetProcessHeap(), 0, itemDelimiterA );
196 return E_OUTOFMEMORY;
198 MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW );
199 HeapFree( GetProcessHeap(), 0, itemDelimiterA );
201 /* read item name string length + 1*/
202 res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
203 if (bread != sizeof(DWORD))
204 return E_FAIL;
206 /* read item name string */
207 if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength)))
208 return E_OUTOFMEMORY;
209 res=IStream_Read(pStm,itemNameA,nameLength,&bread);
210 if (bread != nameLength)
212 HeapFree( GetProcessHeap(), 0, itemNameA );
213 return E_FAIL;
216 lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 );
217 This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR));
218 if (!This->itemName)
220 HeapFree( GetProcessHeap(), 0, itemNameA );
221 return E_OUTOFMEMORY;
223 MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW );
224 HeapFree( GetProcessHeap(), 0, itemNameA );
226 return res;
229 /******************************************************************************
230 * ItemMoniker_Save
231 ******************************************************************************/
232 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
234 ItemMonikerImpl *This = impl_from_IMoniker(iface);
235 HRESULT res;
236 CHAR *itemNameA,*itemDelimiterA;
238 /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
239 /* 2) String (type A): item delimiter string ('\0' included) */
240 /* 3) DWORD : size of item name string ('\0' included) */
241 /* 4) String (type A): item name string ('\0' included) */
243 DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL);
244 DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL);
245 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
246 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
247 WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL);
248 WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL);
250 TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE");
252 res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
253 res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
254 res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
255 res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);
257 HeapFree(GetProcessHeap(), 0, itemNameA);
258 HeapFree(GetProcessHeap(), 0, itemDelimiterA);
260 return res;
263 /******************************************************************************
264 * ItemMoniker_GetSizeMax
265 ******************************************************************************/
266 static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
268 ItemMonikerImpl *This = impl_from_IMoniker(iface);
269 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
270 DWORD nameLength=lstrlenW(This->itemName)+1;
272 TRACE("(%p,%p)\n",iface,pcbSize);
274 if (!pcbSize)
275 return E_POINTER;
277 /* for more details see ItemMonikerImpl_Save comments */
279 pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */
280 delimiterLength*4 + /* item delimiter string */
281 sizeof(DWORD) + /* DWORD which contains item name length */
282 nameLength*4 + /* item name string */
283 18; /* strange, but true */
284 pcbSize->u.HighPart=0;
286 return S_OK;
289 /******************************************************************************
290 * ItemMoniker_BindToObject
291 ******************************************************************************/
292 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
293 IBindCtx* pbc,
294 IMoniker* pmkToLeft,
295 REFIID riid,
296 VOID** ppvResult)
298 ItemMonikerImpl *This = impl_from_IMoniker(iface);
299 HRESULT res;
300 IID refid=IID_IOleItemContainer;
301 IOleItemContainer *poic=0;
303 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
305 if(ppvResult ==NULL)
306 return E_POINTER;
308 if(pmkToLeft==NULL)
309 return E_INVALIDARG;
311 *ppvResult=0;
313 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
315 if (SUCCEEDED(res)){
317 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);
319 IOleItemContainer_Release(poic);
322 return res;
325 /******************************************************************************
326 * ItemMoniker_BindToStorage
327 ******************************************************************************/
328 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
329 IBindCtx* pbc,
330 IMoniker* pmkToLeft,
331 REFIID riid,
332 VOID** ppvResult)
334 ItemMonikerImpl *This = impl_from_IMoniker(iface);
335 HRESULT res;
336 IOleItemContainer *poic=0;
338 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
340 *ppvResult=0;
342 if(pmkToLeft==NULL)
343 return E_INVALIDARG;
345 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
347 if (SUCCEEDED(res)){
349 res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);
351 IOleItemContainer_Release(poic);
354 return res;
357 /******************************************************************************
358 * ItemMoniker_Reduce
359 ******************************************************************************/
360 static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
361 IBindCtx* pbc,
362 DWORD dwReduceHowFar,
363 IMoniker** ppmkToLeft,
364 IMoniker** ppmkReduced)
366 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
368 if (ppmkReduced==NULL)
369 return E_POINTER;
371 ItemMonikerImpl_AddRef(iface);
373 *ppmkReduced=iface;
375 return MK_S_REDUCED_TO_SELF;
377 /******************************************************************************
378 * ItemMoniker_ComposeWith
379 ******************************************************************************/
380 static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
381 IMoniker* pmkRight,
382 BOOL fOnlyIfNotGeneric,
383 IMoniker** ppmkComposite)
385 HRESULT res=S_OK;
386 DWORD mkSys,mkSys2;
387 IEnumMoniker* penumMk=0;
388 IMoniker *pmostLeftMk=0;
389 IMoniker* tempMkComposite=0;
391 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
393 if ((ppmkComposite==NULL)||(pmkRight==NULL))
394 return E_POINTER;
396 *ppmkComposite=0;
398 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
400 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
401 if(mkSys==MKSYS_ANTIMONIKER)
402 return res;
404 else
405 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
406 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
408 if(mkSys==MKSYS_GENERICCOMPOSITE){
410 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
412 if (FAILED(res))
413 return res;
415 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
417 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
419 if(mkSys2==MKSYS_ANTIMONIKER){
421 IMoniker_Release(pmostLeftMk);
423 tempMkComposite=iface;
424 IMoniker_AddRef(iface);
426 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
428 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
430 IMoniker_Release(tempMkComposite);
431 IMoniker_Release(pmostLeftMk);
433 tempMkComposite=*ppmkComposite;
434 IMoniker_AddRef(tempMkComposite);
436 return res;
438 else
439 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
441 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
442 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
443 a NULL moniker and a return value of MK_E_NEEDGENERIC */
444 else
445 if (!fOnlyIfNotGeneric)
446 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
448 else
449 return MK_E_NEEDGENERIC;
452 /******************************************************************************
453 * ItemMoniker_Enum
454 ******************************************************************************/
455 static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
457 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
459 if (ppenumMoniker == NULL)
460 return E_POINTER;
462 *ppenumMoniker = NULL;
464 return S_OK;
467 /******************************************************************************
468 * ItemMoniker_IsEqual
469 ******************************************************************************/
470 static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
473 CLSID clsid;
474 LPOLESTR dispName1,dispName2;
475 IBindCtx* bind;
476 HRESULT res = S_FALSE;
478 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
480 if (!pmkOtherMoniker) return S_FALSE;
483 /* check if both are ItemMoniker */
484 if(FAILED (IMoniker_GetClassID(pmkOtherMoniker,&clsid))) return S_FALSE;
485 if(!IsEqualCLSID(&clsid,&CLSID_ItemMoniker)) return S_FALSE;
487 /* check if both displaynames are the same */
488 if(SUCCEEDED ((res = CreateBindCtx(0,&bind)))) {
489 if(SUCCEEDED (IMoniker_GetDisplayName(iface,bind,NULL,&dispName1))) {
490 if(SUCCEEDED (IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2))) {
491 if(lstrcmpW(dispName1,dispName2)==0) res = S_OK;
492 CoTaskMemFree(dispName2);
494 CoTaskMemFree(dispName1);
497 return res;
500 /******************************************************************************
501 * ItemMoniker_Hash
502 ******************************************************************************/
503 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
505 ItemMonikerImpl *This = impl_from_IMoniker(iface);
506 DWORD h = 0;
507 int i,len;
508 int off = 0;
509 LPOLESTR val;
511 if (pdwHash==NULL)
512 return E_POINTER;
514 val = This->itemName;
515 len = lstrlenW(val);
517 for (i = len ; i > 0; i--)
518 h = (h * 3) ^ toupperW(val[off++]);
520 *pdwHash=h;
522 return S_OK;
525 /******************************************************************************
526 * ItemMoniker_IsRunning
527 ******************************************************************************/
528 static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
529 IBindCtx* pbc,
530 IMoniker* pmkToLeft,
531 IMoniker* pmkNewlyRunning)
533 ItemMonikerImpl *This = impl_from_IMoniker(iface);
534 IRunningObjectTable* rot;
535 HRESULT res;
536 IOleItemContainer *poic=0;
538 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
540 /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
541 /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */
542 if (pmkToLeft==NULL)
543 if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
544 return S_OK;
545 else {
546 if (pbc==NULL)
547 return E_INVALIDARG;
549 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
551 if (FAILED(res))
552 return res;
554 res = IRunningObjectTable_IsRunning(rot,iface);
556 IRunningObjectTable_Release(rot);
558 else{
560 /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */
561 /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
562 /* passing the string contained within this moniker. */
564 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
566 if (SUCCEEDED(res)){
568 res=IOleItemContainer_IsRunning(poic,This->itemName);
570 IOleItemContainer_Release(poic);
574 return res;
577 /******************************************************************************
578 * ItemMoniker_GetTimeOfLastChange
579 ******************************************************************************/
580 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
581 IBindCtx* pbc,
582 IMoniker* pmkToLeft,
583 FILETIME* pItemTime)
585 IRunningObjectTable* rot;
586 HRESULT res;
587 IMoniker *compositeMk;
589 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
591 if (pItemTime==NULL)
592 return E_INVALIDARG;
594 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
595 if (pmkToLeft==NULL)
597 return MK_E_NOTBINDABLE;
598 else {
600 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
601 /* the time of last change. If the object is not in the ROT, the method calls */
602 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
604 res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
606 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
608 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
610 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
612 IMoniker_Release(compositeMk);
615 return res;
618 /******************************************************************************
619 * ItemMoniker_Inverse
620 ******************************************************************************/
621 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
623 TRACE("(%p,%p)\n",iface,ppmk);
625 if (ppmk==NULL)
626 return E_POINTER;
628 return CreateAntiMoniker(ppmk);
631 /******************************************************************************
632 * ItemMoniker_CommonPrefixWith
633 ******************************************************************************/
634 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
636 DWORD mkSys;
638 TRACE("(%p,%p)\n", pmkOther, ppmkPrefix);
640 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
641 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
642 /* to this moniker and returns MK_S_US */
644 if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
646 *ppmkPrefix=iface;
648 IMoniker_AddRef(iface);
650 return MK_S_US;
652 else
653 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
654 /* the case where the other moniker is a generic composite. */
655 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
658 /******************************************************************************
659 * ItemMoniker_RelativePathTo
660 ******************************************************************************/
661 static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
663 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
665 if (ppmkRelPath==NULL)
666 return E_POINTER;
668 *ppmkRelPath=0;
670 return MK_E_NOTBINDABLE;
673 /******************************************************************************
674 * ItemMoniker_GetDisplayName
675 ******************************************************************************/
676 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
677 IBindCtx* pbc,
678 IMoniker* pmkToLeft,
679 LPOLESTR *ppszDisplayName)
681 ItemMonikerImpl *This = impl_from_IMoniker(iface);
683 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
685 if (ppszDisplayName==NULL)
686 return E_POINTER;
688 if (pmkToLeft!=NULL){
689 return E_INVALIDARG;
692 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));
694 if (*ppszDisplayName==NULL)
695 return E_OUTOFMEMORY;
697 lstrcpyW(*ppszDisplayName,This->itemDelimiter);
698 lstrcatW(*ppszDisplayName,This->itemName);
700 TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
702 return S_OK;
705 /******************************************************************************
706 * ItemMoniker_ParseDisplayName
707 ******************************************************************************/
708 static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
709 IBindCtx* pbc,
710 IMoniker* pmkToLeft,
711 LPOLESTR pszDisplayName,
712 ULONG* pchEaten,
713 IMoniker** ppmkOut)
715 ItemMonikerImpl *This = impl_from_IMoniker(iface);
716 IOleItemContainer* poic=0;
717 IParseDisplayName* ppdn=0;
718 LPOLESTR displayName;
719 HRESULT res;
721 TRACE("%s\n", debugstr_w(pszDisplayName));
723 /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
724 if (pmkToLeft==NULL)
726 return MK_E_SYNTAX;
728 else{
729 /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
730 /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */
731 /* name to IParseDisplayName::ParseDisplayName */
732 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
734 if (SUCCEEDED(res)){
736 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
738 res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);
740 res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);
742 IOleItemContainer_Release(poic);
743 IParseDisplayName_Release(ppdn);
746 return res;
749 /******************************************************************************
750 * ItemMoniker_IsSystemMoniker
751 ******************************************************************************/
752 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
754 TRACE("(%p,%p)\n",iface,pwdMksys);
756 if (!pwdMksys)
757 return E_POINTER;
759 (*pwdMksys)=MKSYS_ITEMMONIKER;
761 return S_OK;
764 /*******************************************************************************
765 * ItemMonikerIROTData_QueryInterface
766 *******************************************************************************/
767 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
768 void **ppvObject)
771 ItemMonikerImpl *This = impl_from_IROTData(iface);
773 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
775 return ItemMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
778 /***********************************************************************
779 * ItemMonikerIROTData_AddRef
781 static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
783 ItemMonikerImpl *This = impl_from_IROTData(iface);
785 TRACE("(%p)\n",iface);
787 return ItemMonikerImpl_AddRef(&This->IMoniker_iface);
790 /***********************************************************************
791 * ItemMonikerIROTData_Release
793 static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
795 ItemMonikerImpl *This = impl_from_IROTData(iface);
797 TRACE("(%p)\n",iface);
799 return ItemMonikerImpl_Release(&This->IMoniker_iface);
802 /******************************************************************************
803 * ItemMonikerIROTData_GetComparisonData
804 ******************************************************************************/
805 static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,
806 BYTE* pbData,
807 ULONG cbMax,
808 ULONG* pcbData)
810 ItemMonikerImpl *This = impl_from_IROTData(iface);
811 int len = (strlenW(This->itemName)+1);
812 int i;
813 LPWSTR pszItemName;
814 LPWSTR pszItemDelimiter;
816 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
818 *pcbData = sizeof(CLSID) + sizeof(WCHAR) + len * sizeof(WCHAR);
819 if (cbMax < *pcbData)
820 return E_OUTOFMEMORY;
822 /* write CLSID */
823 memcpy(pbData, &CLSID_ItemMoniker, sizeof(CLSID));
824 /* write delimiter */
825 pszItemDelimiter = (LPWSTR)(pbData+sizeof(CLSID));
826 *pszItemDelimiter = *This->itemDelimiter;
827 /* write name */
828 pszItemName = pszItemDelimiter + 1;
829 for (i = 0; i < len; i++)
830 pszItemName[i] = toupperW(This->itemName[i]);
832 return S_OK;
835 /********************************************************************************/
836 /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/
837 /* IPersistStream and IMoniker functions. */
838 static const IMonikerVtbl VT_ItemMonikerImpl =
840 ItemMonikerImpl_QueryInterface,
841 ItemMonikerImpl_AddRef,
842 ItemMonikerImpl_Release,
843 ItemMonikerImpl_GetClassID,
844 ItemMonikerImpl_IsDirty,
845 ItemMonikerImpl_Load,
846 ItemMonikerImpl_Save,
847 ItemMonikerImpl_GetSizeMax,
848 ItemMonikerImpl_BindToObject,
849 ItemMonikerImpl_BindToStorage,
850 ItemMonikerImpl_Reduce,
851 ItemMonikerImpl_ComposeWith,
852 ItemMonikerImpl_Enum,
853 ItemMonikerImpl_IsEqual,
854 ItemMonikerImpl_Hash,
855 ItemMonikerImpl_IsRunning,
856 ItemMonikerImpl_GetTimeOfLastChange,
857 ItemMonikerImpl_Inverse,
858 ItemMonikerImpl_CommonPrefixWith,
859 ItemMonikerImpl_RelativePathTo,
860 ItemMonikerImpl_GetDisplayName,
861 ItemMonikerImpl_ParseDisplayName,
862 ItemMonikerImpl_IsSystemMoniker
865 /********************************************************************************/
866 /* Virtual function table for the IROTData class. */
867 static const IROTDataVtbl VT_ROTDataImpl =
869 ItemMonikerROTDataImpl_QueryInterface,
870 ItemMonikerROTDataImpl_AddRef,
871 ItemMonikerROTDataImpl_Release,
872 ItemMonikerROTDataImpl_GetComparisonData
875 /******************************************************************************
876 * ItemMoniker_Construct (local function)
877 *******************************************************************************/
878 static HRESULT ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
881 int sizeStr1=lstrlenW(lpszItem), sizeStr2;
882 static const OLECHAR emptystr[1];
883 LPCOLESTR delim;
885 TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem));
887 /* Initialize the virtual function table. */
888 This->IMoniker_iface.lpVtbl = &VT_ItemMonikerImpl;
889 This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
890 This->ref = 0;
891 This->pMarshal = NULL;
893 This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
894 if (!This->itemName)
895 return E_OUTOFMEMORY;
896 lstrcpyW(This->itemName,lpszItem);
898 if (!lpszDelim)
899 FIXME("lpszDelim is NULL. Using empty string which is possibly wrong.\n");
901 delim = lpszDelim ? lpszDelim : emptystr;
903 sizeStr2=lstrlenW(delim);
904 This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
905 if (!This->itemDelimiter) {
906 HeapFree(GetProcessHeap(),0,This->itemName);
907 return E_OUTOFMEMORY;
909 lstrcpyW(This->itemDelimiter,delim);
910 return S_OK;
913 /******************************************************************************
914 * ItemMoniker_Destroy (local function)
915 *******************************************************************************/
916 static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
918 TRACE("(%p)\n",This);
920 if (This->pMarshal) IUnknown_Release(This->pMarshal);
921 HeapFree(GetProcessHeap(),0,This->itemName);
922 HeapFree(GetProcessHeap(),0,This->itemDelimiter);
923 HeapFree(GetProcessHeap(),0,This);
925 return S_OK;
928 /******************************************************************************
929 * CreateItemMoniker [OLE32.@]
930 ******************************************************************************/
931 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim, LPCOLESTR lpszItem, IMoniker **ppmk)
933 ItemMonikerImpl* newItemMoniker;
934 HRESULT hr;
936 TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk);
938 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
940 if (!newItemMoniker)
941 return STG_E_INSUFFICIENTMEMORY;
943 hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
945 if (FAILED(hr)){
947 HeapFree(GetProcessHeap(),0,newItemMoniker);
948 return hr;
951 return ItemMonikerImpl_QueryInterface(&newItemMoniker->IMoniker_iface,&IID_IMoniker,
952 (void**)ppmk);
955 static HRESULT WINAPI ItemMonikerCF_QueryInterface(LPCLASSFACTORY iface,
956 REFIID riid, LPVOID *ppv)
958 *ppv = NULL;
959 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
961 *ppv = iface;
962 IUnknown_AddRef(iface);
963 return S_OK;
965 return E_NOINTERFACE;
968 static ULONG WINAPI ItemMonikerCF_AddRef(LPCLASSFACTORY iface)
970 return 2; /* non-heap based object */
973 static ULONG WINAPI ItemMonikerCF_Release(LPCLASSFACTORY iface)
975 return 1; /* non-heap based object */
978 static HRESULT WINAPI ItemMonikerCF_CreateInstance(LPCLASSFACTORY iface,
979 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
981 ItemMonikerImpl* newItemMoniker;
982 HRESULT hr;
983 static const WCHAR wszEmpty[] = { 0 };
985 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
987 *ppv = NULL;
989 if (pUnk)
990 return CLASS_E_NOAGGREGATION;
992 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
993 if (!newItemMoniker)
994 return E_OUTOFMEMORY;
996 hr = ItemMonikerImpl_Construct(newItemMoniker, wszEmpty, wszEmpty);
998 if (SUCCEEDED(hr))
999 hr = ItemMonikerImpl_QueryInterface(&newItemMoniker->IMoniker_iface, riid, ppv);
1000 if (FAILED(hr))
1001 HeapFree(GetProcessHeap(),0,newItemMoniker);
1003 return hr;
1006 static HRESULT WINAPI ItemMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
1008 FIXME("(%d), stub!\n",fLock);
1009 return S_OK;
1012 static const IClassFactoryVtbl ItemMonikerCFVtbl =
1014 ItemMonikerCF_QueryInterface,
1015 ItemMonikerCF_AddRef,
1016 ItemMonikerCF_Release,
1017 ItemMonikerCF_CreateInstance,
1018 ItemMonikerCF_LockServer
1020 static const IClassFactoryVtbl *ItemMonikerCF = &ItemMonikerCFVtbl;
1022 HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv)
1024 return IClassFactory_QueryInterface((IClassFactory *)&ItemMonikerCF, riid, ppv);