ntdll: Fix race in NtRead/WriteFile.
[wine/testsucceed.git] / dlls / ole32 / itemmoniker.c
blobff8f9b481e36011ecc624a7c44d1eadf42518cc5
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{
44 const IMonikerVtbl* lpvtbl1; /* VTable relative to the IMoniker interface.*/
46 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
47 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
49 const IROTDataVtbl* lpvtbl2; /* VTable relative to the IROTData interface.*/
51 LONG ref; /* reference counter for this object */
53 LPOLESTR itemName; /* item name identified by this ItemMoniker */
55 LPOLESTR itemDelimiter; /* Delimiter string */
57 IUnknown *pMarshal; /* custom marshaler */
58 } ItemMonikerImpl;
60 static inline IMoniker *impl_from_IROTData( IROTData *iface )
62 return (IMoniker *)((char*)iface - FIELD_OFFSET(ItemMonikerImpl, lpvtbl2));
65 static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
67 /*******************************************************************************
68 * ItemMoniker_QueryInterface
69 *******************************************************************************/
70 static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
72 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
74 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
76 /* Perform a sanity check on the parameters.*/
77 if ( (This==0) || (ppvObject==0) )
78 return E_INVALIDARG;
80 /* Initialize the return parameter */
81 *ppvObject = 0;
83 /* Compare the riid with the interface IDs implemented by this object.*/
84 if (IsEqualIID(&IID_IUnknown, riid) ||
85 IsEqualIID(&IID_IPersist, riid) ||
86 IsEqualIID(&IID_IPersistStream, riid) ||
87 IsEqualIID(&IID_IMoniker, riid)
89 *ppvObject = iface;
91 else if (IsEqualIID(&IID_IROTData, riid))
92 *ppvObject = &This->lpvtbl2;
93 else if (IsEqualIID(&IID_IMarshal, riid))
95 HRESULT hr = S_OK;
96 if (!This->pMarshal)
97 hr = MonikerMarshal_Create(iface, &This->pMarshal);
98 if (hr != S_OK)
99 return hr;
100 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
103 /* Check that we obtained an interface.*/
104 if ((*ppvObject)==0)
105 return E_NOINTERFACE;
107 /* Query Interface always increases the reference count by one when it is successful */
108 IMoniker_AddRef(iface);
110 return S_OK;
113 /******************************************************************************
114 * ItemMoniker_AddRef
115 ******************************************************************************/
116 static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
118 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
120 TRACE("(%p)\n",This);
122 return InterlockedIncrement(&This->ref);
125 /******************************************************************************
126 * ItemMoniker_Release
127 ******************************************************************************/
128 static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
130 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
131 ULONG ref;
133 TRACE("(%p)\n",This);
135 ref = InterlockedDecrement(&This->ref);
137 /* destroy the object if there's no more reference on it */
138 if (ref == 0) ItemMonikerImpl_Destroy(This);
140 return ref;
143 /******************************************************************************
144 * ItemMoniker_GetClassID
145 ******************************************************************************/
146 static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
148 TRACE("(%p,%p)\n",iface,pClassID);
150 if (pClassID==NULL)
151 return E_POINTER;
153 *pClassID = CLSID_ItemMoniker;
155 return S_OK;
158 /******************************************************************************
159 * ItemMoniker_IsDirty
160 ******************************************************************************/
161 static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
163 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
164 method in the OLE-provided moniker interfaces always return S_FALSE because
165 their internal state never changes. */
167 TRACE("(%p)\n",iface);
169 return S_FALSE;
172 /******************************************************************************
173 * ItemMoniker_Load
174 ******************************************************************************/
175 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
178 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
179 HRESULT res;
180 DWORD delimiterLength,nameLength,lenW;
181 CHAR *itemNameA,*itemDelimiterA;
182 ULONG bread;
184 TRACE("\n");
186 /* for more details about data read by this function see comments of ItemMonikerImpl_Save function */
188 /* read item delimiter string length + 1 */
189 res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);
190 if (bread != sizeof(DWORD))
191 return E_FAIL;
193 /* read item delimiter string */
194 if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength)))
195 return E_OUTOFMEMORY;
196 res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
197 if (bread != delimiterLength)
199 HeapFree( GetProcessHeap(), 0, itemDelimiterA );
200 return E_FAIL;
203 lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 );
204 This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR));
205 if (!This->itemDelimiter)
207 HeapFree( GetProcessHeap(), 0, itemDelimiterA );
208 return E_OUTOFMEMORY;
210 MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW );
211 HeapFree( GetProcessHeap(), 0, itemDelimiterA );
213 /* read item name string length + 1*/
214 res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
215 if (bread != sizeof(DWORD))
216 return E_FAIL;
218 /* read item name string */
219 if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength)))
220 return E_OUTOFMEMORY;
221 res=IStream_Read(pStm,itemNameA,nameLength,&bread);
222 if (bread != nameLength)
224 HeapFree( GetProcessHeap(), 0, itemNameA );
225 return E_FAIL;
228 lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 );
229 This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR));
230 if (!This->itemName)
232 HeapFree( GetProcessHeap(), 0, itemNameA );
233 return E_OUTOFMEMORY;
235 MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW );
236 HeapFree( GetProcessHeap(), 0, itemNameA );
238 return res;
241 /******************************************************************************
242 * ItemMoniker_Save
243 ******************************************************************************/
244 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,
245 IStream* pStm,/* pointer to the stream where the object is to be saved */
246 BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
248 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
249 HRESULT res;
250 CHAR *itemNameA,*itemDelimiterA;
252 /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
253 /* 2) String (type A): item delimiter string ('\0' included) */
254 /* 3) DWORD : size of item name string ('\0' included) */
255 /* 4) String (type A): item name string ('\0' included) */
257 DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL);
258 DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL);
259 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
260 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
261 WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL);
262 WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL);
264 TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE");
266 res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
267 res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
268 res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
269 res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);
271 HeapFree(GetProcessHeap(), 0, itemNameA);
272 HeapFree(GetProcessHeap(), 0, itemDelimiterA);
274 return res;
277 /******************************************************************************
278 * ItemMoniker_GetSizeMax
279 ******************************************************************************/
280 static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,
281 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
283 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
284 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
285 DWORD nameLength=lstrlenW(This->itemName)+1;
287 TRACE("(%p,%p)\n",iface,pcbSize);
289 if (!pcbSize)
290 return E_POINTER;
292 /* for more details see ItemMonikerImpl_Save comments */
294 pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */
295 delimiterLength*4 + /* item delimiter string */
296 sizeof(DWORD) + /* DWORD which contains item name length */
297 nameLength*4 + /* item name string */
298 18; /* strange, but true */
299 pcbSize->u.HighPart=0;
301 return S_OK;
304 /******************************************************************************
305 * ItemMoniker_BindToObject
306 ******************************************************************************/
307 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
308 IBindCtx* pbc,
309 IMoniker* pmkToLeft,
310 REFIID riid,
311 VOID** ppvResult)
313 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
315 HRESULT res;
316 IID refid=IID_IOleItemContainer;
317 IOleItemContainer *poic=0;
319 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
321 if(ppvResult ==NULL)
322 return E_POINTER;
324 if(pmkToLeft==NULL)
325 return E_INVALIDARG;
327 *ppvResult=0;
329 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
331 if (SUCCEEDED(res)){
333 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);
335 IOleItemContainer_Release(poic);
338 return res;
341 /******************************************************************************
342 * ItemMoniker_BindToStorage
343 ******************************************************************************/
344 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
345 IBindCtx* pbc,
346 IMoniker* pmkToLeft,
347 REFIID riid,
348 VOID** ppvResult)
350 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
352 HRESULT res;
353 IOleItemContainer *poic=0;
355 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
357 *ppvResult=0;
359 if(pmkToLeft==NULL)
360 return E_INVALIDARG;
362 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
364 if (SUCCEEDED(res)){
366 res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);
368 IOleItemContainer_Release(poic);
371 return res;
374 /******************************************************************************
375 * ItemMoniker_Reduce
376 ******************************************************************************/
377 static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
378 IBindCtx* pbc,
379 DWORD dwReduceHowFar,
380 IMoniker** ppmkToLeft,
381 IMoniker** ppmkReduced)
383 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
385 if (ppmkReduced==NULL)
386 return E_POINTER;
388 ItemMonikerImpl_AddRef(iface);
390 *ppmkReduced=iface;
392 return MK_S_REDUCED_TO_SELF;
394 /******************************************************************************
395 * ItemMoniker_ComposeWith
396 ******************************************************************************/
397 static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
398 IMoniker* pmkRight,
399 BOOL fOnlyIfNotGeneric,
400 IMoniker** ppmkComposite)
402 HRESULT res=S_OK;
403 DWORD mkSys,mkSys2;
404 IEnumMoniker* penumMk=0;
405 IMoniker *pmostLeftMk=0;
406 IMoniker* tempMkComposite=0;
408 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
410 if ((ppmkComposite==NULL)||(pmkRight==NULL))
411 return E_POINTER;
413 *ppmkComposite=0;
415 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
417 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
418 if(mkSys==MKSYS_ANTIMONIKER)
419 return res;
421 else
422 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
423 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
425 if(mkSys==MKSYS_GENERICCOMPOSITE){
427 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
429 if (FAILED(res))
430 return res;
432 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
434 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
436 if(mkSys2==MKSYS_ANTIMONIKER){
438 IMoniker_Release(pmostLeftMk);
440 tempMkComposite=iface;
441 IMoniker_AddRef(iface);
443 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
445 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
447 IMoniker_Release(tempMkComposite);
448 IMoniker_Release(pmostLeftMk);
450 tempMkComposite=*ppmkComposite;
451 IMoniker_AddRef(tempMkComposite);
453 return res;
455 else
456 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
458 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
459 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
460 a NULL moniker and a return value of MK_E_NEEDGENERIC */
461 else
462 if (!fOnlyIfNotGeneric)
463 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
465 else
466 return MK_E_NEEDGENERIC;
469 /******************************************************************************
470 * ItemMoniker_Enum
471 ******************************************************************************/
472 static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
474 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
476 if (ppenumMoniker == NULL)
477 return E_POINTER;
479 *ppenumMoniker = NULL;
481 return S_OK;
484 /******************************************************************************
485 * ItemMoniker_IsEqual
486 ******************************************************************************/
487 static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
490 CLSID clsid;
491 LPOLESTR dispName1,dispName2;
492 IBindCtx* bind;
493 HRESULT res = S_FALSE;
495 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
497 if (!pmkOtherMoniker) return S_FALSE;
500 /* check if both are ItemMoniker */
501 if(FAILED (IMoniker_GetClassID(pmkOtherMoniker,&clsid))) return S_FALSE;
502 if(!IsEqualCLSID(&clsid,&CLSID_ItemMoniker)) return S_FALSE;
504 /* check if both displaynames are the same */
505 if(SUCCEEDED ((res = CreateBindCtx(0,&bind)))) {
506 if(SUCCEEDED (IMoniker_GetDisplayName(iface,bind,NULL,&dispName1))) {
507 if(SUCCEEDED (IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2))) {
508 if(lstrcmpW(dispName1,dispName2)==0) res = S_OK;
509 CoTaskMemFree(dispName2);
511 CoTaskMemFree(dispName1);
514 return res;
517 /******************************************************************************
518 * ItemMoniker_Hash
519 ******************************************************************************/
520 static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
522 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
523 DWORD h = 0;
524 int i,len;
525 int off = 0;
526 LPOLESTR val;
528 if (pdwHash==NULL)
529 return E_POINTER;
531 val = This->itemName;
532 len = lstrlenW(val);
534 for (i = len ; i > 0; i--)
535 h = (h * 3) ^ toupperW(val[off++]);
537 *pdwHash=h;
539 return S_OK;
542 /******************************************************************************
543 * ItemMoniker_IsRunning
544 ******************************************************************************/
545 static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
546 IBindCtx* pbc,
547 IMoniker* pmkToLeft,
548 IMoniker* pmkNewlyRunning)
550 IRunningObjectTable* rot;
551 HRESULT res;
552 IOleItemContainer *poic=0;
553 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
555 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
557 /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
558 /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */
559 if (pmkToLeft==NULL)
560 if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
561 return S_OK;
562 else {
563 if (pbc==NULL)
564 return E_INVALIDARG;
566 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
568 if (FAILED(res))
569 return res;
571 res = IRunningObjectTable_IsRunning(rot,iface);
573 IRunningObjectTable_Release(rot);
575 else{
577 /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */
578 /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
579 /* passing the string contained within this moniker. */
581 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
583 if (SUCCEEDED(res)){
585 res=IOleItemContainer_IsRunning(poic,This->itemName);
587 IOleItemContainer_Release(poic);
591 return res;
594 /******************************************************************************
595 * ItemMoniker_GetTimeOfLastChange
596 ******************************************************************************/
597 static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
598 IBindCtx* pbc,
599 IMoniker* pmkToLeft,
600 FILETIME* pItemTime)
602 IRunningObjectTable* rot;
603 HRESULT res;
604 IMoniker *compositeMk;
606 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
608 if (pItemTime==NULL)
609 return E_INVALIDARG;
611 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
612 if (pmkToLeft==NULL)
614 return MK_E_NOTBINDABLE;
615 else {
617 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
618 /* the time of last change. If the object is not in the ROT, the method calls */
619 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
621 res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
623 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
625 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
627 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
629 IMoniker_Release(compositeMk);
632 return res;
635 /******************************************************************************
636 * ItemMoniker_Inverse
637 ******************************************************************************/
638 static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
640 TRACE("(%p,%p)\n",iface,ppmk);
642 if (ppmk==NULL)
643 return E_POINTER;
645 return CreateAntiMoniker(ppmk);
648 /******************************************************************************
649 * ItemMoniker_CommonPrefixWith
650 ******************************************************************************/
651 static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
653 DWORD mkSys;
655 TRACE("(%p,%p)\n", pmkOther, ppmkPrefix);
657 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
658 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
659 /* to this moniker and returns MK_S_US */
661 if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
663 *ppmkPrefix=iface;
665 IMoniker_AddRef(iface);
667 return MK_S_US;
669 else
670 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
671 /* the case where the other moniker is a generic composite. */
672 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
675 /******************************************************************************
676 * ItemMoniker_RelativePathTo
677 ******************************************************************************/
678 static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
680 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
682 if (ppmkRelPath==NULL)
683 return E_POINTER;
685 *ppmkRelPath=0;
687 return MK_E_NOTBINDABLE;
690 /******************************************************************************
691 * ItemMoniker_GetDisplayName
692 ******************************************************************************/
693 static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
694 IBindCtx* pbc,
695 IMoniker* pmkToLeft,
696 LPOLESTR *ppszDisplayName)
698 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
700 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
702 if (ppszDisplayName==NULL)
703 return E_POINTER;
705 if (pmkToLeft!=NULL){
706 return E_INVALIDARG;
709 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));
711 if (*ppszDisplayName==NULL)
712 return E_OUTOFMEMORY;
714 lstrcpyW(*ppszDisplayName,This->itemDelimiter);
715 lstrcatW(*ppszDisplayName,This->itemName);
717 TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
719 return S_OK;
722 /******************************************************************************
723 * ItemMoniker_ParseDisplayName
724 ******************************************************************************/
725 static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
726 IBindCtx* pbc,
727 IMoniker* pmkToLeft,
728 LPOLESTR pszDisplayName,
729 ULONG* pchEaten,
730 IMoniker** ppmkOut)
732 IOleItemContainer* poic=0;
733 IParseDisplayName* ppdn=0;
734 LPOLESTR displayName;
735 HRESULT res;
736 ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
738 TRACE("%s\n", debugstr_w(pszDisplayName));
740 /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
741 if (pmkToLeft==NULL)
743 return MK_E_SYNTAX;
745 else{
746 /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
747 /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */
748 /* name to IParseDisplayName::ParseDisplayName */
749 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
751 if (SUCCEEDED(res)){
753 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
755 res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);
757 res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);
759 IOleItemContainer_Release(poic);
760 IParseDisplayName_Release(ppdn);
763 return res;
766 /******************************************************************************
767 * ItemMoniker_IsSystemMoniker
768 ******************************************************************************/
769 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
771 TRACE("(%p,%p)\n",iface,pwdMksys);
773 if (!pwdMksys)
774 return E_POINTER;
776 (*pwdMksys)=MKSYS_ITEMMONIKER;
778 return S_OK;
781 /*******************************************************************************
782 * ItemMonikerIROTData_QueryInterface
783 *******************************************************************************/
784 static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
787 IMoniker *This = impl_from_IROTData(iface);
789 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
791 return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);
794 /***********************************************************************
795 * ItemMonikerIROTData_AddRef
797 static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
799 IMoniker *This = impl_from_IROTData(iface);
801 TRACE("(%p)\n",iface);
803 return ItemMonikerImpl_AddRef(This);
806 /***********************************************************************
807 * ItemMonikerIROTData_Release
809 static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
811 IMoniker *This = impl_from_IROTData(iface);
813 TRACE("(%p)\n",iface);
815 return ItemMonikerImpl_Release(This);
818 /******************************************************************************
819 * ItemMonikerIROTData_GetComparisonData
820 ******************************************************************************/
821 static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,
822 BYTE* pbData,
823 ULONG cbMax,
824 ULONG* pcbData)
826 IMoniker *This = impl_from_IROTData(iface);
827 ItemMonikerImpl *This1 = (ItemMonikerImpl *)This;
828 int len = (strlenW(This1->itemName)+1);
829 int i;
830 LPWSTR pszItemName;
831 LPWSTR pszItemDelimiter;
833 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
835 *pcbData = sizeof(CLSID) + sizeof(WCHAR) + len * sizeof(WCHAR);
836 if (cbMax < *pcbData)
837 return E_OUTOFMEMORY;
839 /* write CLSID */
840 memcpy(pbData, &CLSID_ItemMoniker, sizeof(CLSID));
841 /* write delimiter */
842 pszItemDelimiter = (LPWSTR)(pbData+sizeof(CLSID));
843 *pszItemDelimiter = *This1->itemDelimiter;
844 /* write name */
845 pszItemName = pszItemDelimiter + 1;
846 for (i = 0; i < len; i++)
847 pszItemName[i] = toupperW(This1->itemName[i]);
849 return S_OK;
852 /********************************************************************************/
853 /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/
854 /* IPersistStream and IMoniker functions. */
855 static const IMonikerVtbl VT_ItemMonikerImpl =
857 ItemMonikerImpl_QueryInterface,
858 ItemMonikerImpl_AddRef,
859 ItemMonikerImpl_Release,
860 ItemMonikerImpl_GetClassID,
861 ItemMonikerImpl_IsDirty,
862 ItemMonikerImpl_Load,
863 ItemMonikerImpl_Save,
864 ItemMonikerImpl_GetSizeMax,
865 ItemMonikerImpl_BindToObject,
866 ItemMonikerImpl_BindToStorage,
867 ItemMonikerImpl_Reduce,
868 ItemMonikerImpl_ComposeWith,
869 ItemMonikerImpl_Enum,
870 ItemMonikerImpl_IsEqual,
871 ItemMonikerImpl_Hash,
872 ItemMonikerImpl_IsRunning,
873 ItemMonikerImpl_GetTimeOfLastChange,
874 ItemMonikerImpl_Inverse,
875 ItemMonikerImpl_CommonPrefixWith,
876 ItemMonikerImpl_RelativePathTo,
877 ItemMonikerImpl_GetDisplayName,
878 ItemMonikerImpl_ParseDisplayName,
879 ItemMonikerImpl_IsSystemMoniker
882 /********************************************************************************/
883 /* Virtual function table for the IROTData class. */
884 static const IROTDataVtbl VT_ROTDataImpl =
886 ItemMonikerROTDataImpl_QueryInterface,
887 ItemMonikerROTDataImpl_AddRef,
888 ItemMonikerROTDataImpl_Release,
889 ItemMonikerROTDataImpl_GetComparisonData
892 /******************************************************************************
893 * ItemMoniker_Construct (local function)
894 *******************************************************************************/
895 static HRESULT ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
898 int sizeStr1=lstrlenW(lpszItem), sizeStr2;
899 static const OLECHAR emptystr[1];
900 LPCOLESTR delim;
902 TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem));
904 /* Initialize the virtual function table. */
905 This->lpvtbl1 = &VT_ItemMonikerImpl;
906 This->lpvtbl2 = &VT_ROTDataImpl;
907 This->ref = 0;
908 This->pMarshal = NULL;
910 This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
911 if (!This->itemName)
912 return E_OUTOFMEMORY;
913 lstrcpyW(This->itemName,lpszItem);
915 if (!lpszDelim)
916 FIXME("lpszDelim is NULL. Using empty string which is possibly wrong.\n");
918 delim = lpszDelim ? lpszDelim : emptystr;
920 sizeStr2=lstrlenW(delim);
921 This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
922 if (!This->itemDelimiter) {
923 HeapFree(GetProcessHeap(),0,This->itemName);
924 return E_OUTOFMEMORY;
926 lstrcpyW(This->itemDelimiter,delim);
927 return S_OK;
930 /******************************************************************************
931 * ItemMoniker_Destroy (local function)
932 *******************************************************************************/
933 static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
935 TRACE("(%p)\n",This);
937 if (This->pMarshal) IUnknown_Release(This->pMarshal);
938 HeapFree(GetProcessHeap(),0,This->itemName);
939 HeapFree(GetProcessHeap(),0,This->itemDelimiter);
940 HeapFree(GetProcessHeap(),0,This);
942 return S_OK;
945 /******************************************************************************
946 * CreateItemMoniker [OLE32.@]
947 ******************************************************************************/
948 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk)
950 ItemMonikerImpl* newItemMoniker;
951 HRESULT hr;
953 TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk);
955 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
957 if (!newItemMoniker)
958 return STG_E_INSUFFICIENTMEMORY;
960 hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
962 if (FAILED(hr)){
964 HeapFree(GetProcessHeap(),0,newItemMoniker);
965 return hr;
968 return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&IID_IMoniker,(void**)ppmk);
971 static HRESULT WINAPI ItemMonikerCF_QueryInterface(LPCLASSFACTORY iface,
972 REFIID riid, LPVOID *ppv)
974 *ppv = NULL;
975 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
977 *ppv = iface;
978 IUnknown_AddRef(iface);
979 return S_OK;
981 return E_NOINTERFACE;
984 static ULONG WINAPI ItemMonikerCF_AddRef(LPCLASSFACTORY iface)
986 return 2; /* non-heap based object */
989 static ULONG WINAPI ItemMonikerCF_Release(LPCLASSFACTORY iface)
991 return 1; /* non-heap based object */
994 static HRESULT WINAPI ItemMonikerCF_CreateInstance(LPCLASSFACTORY iface,
995 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
997 ItemMonikerImpl* newItemMoniker;
998 HRESULT hr;
999 static const WCHAR wszEmpty[] = { 0 };
1001 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
1003 *ppv = NULL;
1005 if (pUnk)
1006 return CLASS_E_NOAGGREGATION;
1008 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
1009 if (!newItemMoniker)
1010 return E_OUTOFMEMORY;
1012 hr = ItemMonikerImpl_Construct(newItemMoniker, wszEmpty, wszEmpty);
1014 if (SUCCEEDED(hr))
1015 hr = ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker, riid, ppv);
1016 if (FAILED(hr))
1017 HeapFree(GetProcessHeap(),0,newItemMoniker);
1019 return hr;
1022 static HRESULT WINAPI ItemMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
1024 FIXME("(%d), stub!\n",fLock);
1025 return S_OK;
1028 static const IClassFactoryVtbl ItemMonikerCFVtbl =
1030 ItemMonikerCF_QueryInterface,
1031 ItemMonikerCF_AddRef,
1032 ItemMonikerCF_Release,
1033 ItemMonikerCF_CreateInstance,
1034 ItemMonikerCF_LockServer
1036 static const IClassFactoryVtbl *ItemMonikerCF = &ItemMonikerCFVtbl;
1038 HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv)
1040 return IClassFactory_QueryInterface((IClassFactory *)&ItemMonikerCF, riid, ppv);