2 * Pointer Moniker Implementation
4 * Copyright 1999 Noomen Hamza
5 * Copyright 2008 Robert Shearman (for CodeWeavers)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
35 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
40 /* PointerMoniker data structure */
41 typedef struct PointerMonikerImpl
{
43 IMoniker IMoniker_iface
;
45 LONG ref
; /* reference counter for this object */
47 IUnknown
*pObject
; /* custom marshaler */
50 static inline PointerMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
52 return CONTAINING_RECORD(iface
, PointerMonikerImpl
, IMoniker_iface
);
56 PointerMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
58 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
60 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
62 /* Perform a sanity check on the parameters.*/
63 if ( (This
==0) || (ppvObject
==0) )
66 /* Initialize the return parameter */
69 /* Compare the riid with the interface IDs implemented by this object.*/
70 if (IsEqualIID(&IID_IUnknown
, riid
) ||
71 IsEqualIID(&IID_IPersist
, riid
) ||
72 IsEqualIID(&IID_IPersistStream
, riid
) ||
73 IsEqualIID(&IID_IMoniker
, riid
))
76 /* Check that we obtained an interface.*/
80 /* always increase the reference count by one when it is successful */
81 IMoniker_AddRef(iface
);
86 /******************************************************************************
87 * PointerMoniker_AddRef
88 ******************************************************************************/
90 PointerMonikerImpl_AddRef(IMoniker
* iface
)
92 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
96 return InterlockedIncrement(&This
->ref
);
99 /******************************************************************************
100 * PointerMoniker_Release
101 ******************************************************************************/
103 PointerMonikerImpl_Release(IMoniker
* iface
)
105 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
108 TRACE("(%p)\n",This
);
110 ref
= InterlockedDecrement(&This
->ref
);
112 /* destroy the object if there's no more reference on it */
115 if (This
->pObject
) IUnknown_Release(This
->pObject
);
116 HeapFree(GetProcessHeap(),0,This
);
122 /******************************************************************************
123 * PointerMoniker_GetClassID
124 ******************************************************************************/
125 static HRESULT WINAPI
126 PointerMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
128 TRACE("(%p,%p)\n",iface
,pClassID
);
133 *pClassID
= CLSID_PointerMoniker
;
138 /******************************************************************************
139 * PointerMoniker_IsDirty
140 ******************************************************************************/
141 static HRESULT WINAPI
142 PointerMonikerImpl_IsDirty(IMoniker
* iface
)
144 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
145 method in the OLE-provided moniker interfaces always return S_FALSE because
146 their internal state never changes. */
148 TRACE("(%p)\n",iface
);
153 /******************************************************************************
154 * PointerMoniker_Load
155 ******************************************************************************/
156 static HRESULT WINAPI
157 PointerMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
159 TRACE("(%p)\n", pStm
);
164 /******************************************************************************
165 * PointerMoniker_Save
166 ******************************************************************************/
167 static HRESULT WINAPI
168 PointerMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
)
170 TRACE("(%p, %d)\n", pStm
, fClearDirty
);
175 /******************************************************************************
176 * PointerMoniker_GetSizeMax
179 * pcbSize [out] Pointer to size of stream needed to save object
180 ******************************************************************************/
181 static HRESULT WINAPI
182 PointerMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
)
184 TRACE("(%p,%p)\n",iface
,pcbSize
);
189 pcbSize
->u
.LowPart
= 0;
190 pcbSize
->u
.HighPart
= 0;
195 /******************************************************************************
196 * PointerMoniker_BindToObject
197 ******************************************************************************/
198 static HRESULT WINAPI
199 PointerMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
200 REFIID riid
, VOID
** ppvResult
)
202 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
204 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
209 return IUnknown_QueryInterface(This
->pObject
, riid
, ppvResult
);
212 /******************************************************************************
213 * PointerMoniker_BindToStorage
214 ******************************************************************************/
215 static HRESULT WINAPI
216 PointerMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
217 REFIID riid
, VOID
** ppvResult
)
219 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
221 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
226 return IUnknown_QueryInterface(This
->pObject
, riid
, ppvResult
);
229 /******************************************************************************
230 * PointerMoniker_Reduce
231 ******************************************************************************/
232 static HRESULT WINAPI
233 PointerMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
234 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
236 TRACE("(%p,%p,%d,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
238 if (ppmkReduced
==NULL
)
241 PointerMonikerImpl_AddRef(iface
);
245 return MK_S_REDUCED_TO_SELF
;
247 /******************************************************************************
248 * PointerMoniker_ComposeWith
249 ******************************************************************************/
250 static HRESULT WINAPI
251 PointerMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
252 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
257 IEnumMoniker
* penumMk
=0;
258 IMoniker
*pmostLeftMk
=0;
259 IMoniker
* tempMkComposite
=0;
261 TRACE("(%p,%d,%p)\n", pmkRight
, fOnlyIfNotGeneric
, ppmkComposite
);
263 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
268 IMoniker_IsSystemMoniker(pmkRight
,&mkSys
);
270 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
271 if(mkSys
==MKSYS_ANTIMONIKER
)
275 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
276 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
278 if(mkSys
==MKSYS_GENERICCOMPOSITE
){
280 res
=IMoniker_Enum(pmkRight
,TRUE
,&penumMk
);
285 res
=IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
);
287 IMoniker_IsSystemMoniker(pmostLeftMk
,&mkSys2
);
289 if(mkSys2
==MKSYS_ANTIMONIKER
){
291 IMoniker_Release(pmostLeftMk
);
293 tempMkComposite
=iface
;
294 IMoniker_AddRef(iface
);
296 while(IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
)==S_OK
){
298 res
=CreateGenericComposite(tempMkComposite
,pmostLeftMk
,ppmkComposite
);
300 IMoniker_Release(tempMkComposite
);
301 IMoniker_Release(pmostLeftMk
);
303 tempMkComposite
=*ppmkComposite
;
304 IMoniker_AddRef(tempMkComposite
);
309 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
311 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
312 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
313 a NULL moniker and a return value of MK_E_NEEDGENERIC */
315 if (!fOnlyIfNotGeneric
)
316 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
319 return MK_E_NEEDGENERIC
;
322 /******************************************************************************
323 * PointerMoniker_Enum
324 ******************************************************************************/
325 static HRESULT WINAPI
326 PointerMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
328 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
330 if (ppenumMoniker
== NULL
)
333 *ppenumMoniker
= NULL
;
338 /******************************************************************************
339 * PointerMoniker_IsEqual
340 ******************************************************************************/
341 static HRESULT WINAPI
342 PointerMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
344 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
347 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
349 if (pmkOtherMoniker
==NULL
)
352 IMoniker_IsSystemMoniker(pmkOtherMoniker
,&mkSys
);
354 if (mkSys
==MKSYS_POINTERMONIKER
)
356 PointerMonikerImpl
*pOtherMoniker
= impl_from_IMoniker(pmkOtherMoniker
);
357 return This
->pObject
== pOtherMoniker
->pObject
? S_OK
: S_FALSE
;
363 /******************************************************************************
364 * PointerMoniker_Hash
365 ******************************************************************************/
366 static HRESULT WINAPI
PointerMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
368 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
373 *pdwHash
= PtrToUlong(This
->pObject
);
378 /******************************************************************************
379 * PointerMoniker_IsRunning
380 ******************************************************************************/
381 static HRESULT WINAPI
382 PointerMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
383 IMoniker
* pmkNewlyRunning
)
385 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
390 /******************************************************************************
391 * PointerMoniker_GetTimeOfLastChange
392 ******************************************************************************/
393 static HRESULT WINAPI
PointerMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
398 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pAntiTime
);
402 /******************************************************************************
403 * PointerMoniker_Inverse
404 ******************************************************************************/
405 static HRESULT WINAPI
406 PointerMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
408 TRACE("(%p,%p)\n",iface
,ppmk
);
410 return CreateAntiMoniker(ppmk
);
413 /******************************************************************************
414 * PointerMoniker_CommonPrefixWith
415 ******************************************************************************/
416 static HRESULT WINAPI
417 PointerMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
419 TRACE("(%p, %p)\n", pmkOther
, ppmkPrefix
);
423 if (PointerMonikerImpl_IsEqual(iface
, pmkOther
))
425 IMoniker_AddRef(iface
);
432 return MK_E_NOPREFIX
;
435 /******************************************************************************
436 * PointerMoniker_RelativePathTo
437 ******************************************************************************/
438 static HRESULT WINAPI
439 PointerMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
)
441 TRACE("(%p,%p,%p)\n",iface
,pmOther
,ppmkRelPath
);
443 if (ppmkRelPath
==NULL
)
451 /******************************************************************************
452 * PointerMoniker_GetDisplayName
453 ******************************************************************************/
454 static HRESULT WINAPI
455 PointerMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
456 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
458 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
460 if (ppszDisplayName
==NULL
)
463 *ppszDisplayName
= NULL
;
467 /******************************************************************************
468 * PointerMoniker_ParseDisplayName
469 ******************************************************************************/
470 static HRESULT WINAPI
471 PointerMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
472 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
,
473 ULONG
* pchEaten
, IMoniker
** ppmkOut
)
475 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
477 IParseDisplayName
*pPDN
;
479 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pszDisplayName
,pchEaten
,ppmkOut
);
487 hr
= IUnknown_QueryInterface(This
->pObject
, &IID_IParseDisplayName
, (void **)&pPDN
);
491 hr
= IParseDisplayName_ParseDisplayName(pPDN
, pbc
, pszDisplayName
, pchEaten
, ppmkOut
);
492 IParseDisplayName_Release(pPDN
);
497 /******************************************************************************
498 * PointerMoniker_IsSystemMoniker
499 ******************************************************************************/
500 static HRESULT WINAPI
501 PointerMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
503 TRACE("(%p,%p)\n",iface
,pwdMksys
);
508 *pwdMksys
= MKSYS_POINTERMONIKER
;
513 /********************************************************************************/
514 /* Virtual function table for the PointerMonikerImpl class which include IPersist,*/
515 /* IPersistStream and IMoniker functions. */
516 static const IMonikerVtbl VT_PointerMonikerImpl
=
518 PointerMonikerImpl_QueryInterface
,
519 PointerMonikerImpl_AddRef
,
520 PointerMonikerImpl_Release
,
521 PointerMonikerImpl_GetClassID
,
522 PointerMonikerImpl_IsDirty
,
523 PointerMonikerImpl_Load
,
524 PointerMonikerImpl_Save
,
525 PointerMonikerImpl_GetSizeMax
,
526 PointerMonikerImpl_BindToObject
,
527 PointerMonikerImpl_BindToStorage
,
528 PointerMonikerImpl_Reduce
,
529 PointerMonikerImpl_ComposeWith
,
530 PointerMonikerImpl_Enum
,
531 PointerMonikerImpl_IsEqual
,
532 PointerMonikerImpl_Hash
,
533 PointerMonikerImpl_IsRunning
,
534 PointerMonikerImpl_GetTimeOfLastChange
,
535 PointerMonikerImpl_Inverse
,
536 PointerMonikerImpl_CommonPrefixWith
,
537 PointerMonikerImpl_RelativePathTo
,
538 PointerMonikerImpl_GetDisplayName
,
539 PointerMonikerImpl_ParseDisplayName
,
540 PointerMonikerImpl_IsSystemMoniker
543 /******************************************************************************
544 * PointerMoniker_Construct (local function)
545 *******************************************************************************/
546 static void PointerMonikerImpl_Construct(PointerMonikerImpl
* This
, IUnknown
*punk
)
548 TRACE("(%p)\n",This
);
550 /* Initialize the virtual function table. */
551 This
->IMoniker_iface
.lpVtbl
= &VT_PointerMonikerImpl
;
554 IUnknown_AddRef(punk
);
555 This
->pObject
= punk
;
558 /***********************************************************************
559 * CreatePointerMoniker (OLE32.@)
561 * Creates a moniker which represents a pointer.
564 * punk [I] Pointer to the object to represent.
565 * ppmk [O] Address that receives the pointer to the created moniker.
569 * Failure: Any HRESULT code.
571 HRESULT WINAPI
CreatePointerMoniker(LPUNKNOWN punk
, LPMONIKER
*ppmk
)
573 PointerMonikerImpl
*This
;
575 TRACE("(%p, %p)\n", punk
, ppmk
);
580 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
584 return E_OUTOFMEMORY
;
587 PointerMonikerImpl_Construct(This
, punk
);
588 *ppmk
= &This
->IMoniker_iface
;
592 static HRESULT WINAPI
PointerMonikerCF_QueryInterface(LPCLASSFACTORY iface
,
593 REFIID riid
, LPVOID
*ppv
)
596 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
599 IClassFactory_AddRef(iface
);
602 return E_NOINTERFACE
;
605 static ULONG WINAPI
PointerMonikerCF_AddRef(LPCLASSFACTORY iface
)
607 return 2; /* non-heap based object */
610 static ULONG WINAPI
PointerMonikerCF_Release(LPCLASSFACTORY iface
)
612 return 1; /* non-heap based object */
615 static HRESULT WINAPI
PointerMonikerCF_CreateInstance(LPCLASSFACTORY iface
,
616 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
621 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
626 return CLASS_E_NOAGGREGATION
;
628 hr
= CreatePointerMoniker(NULL
, &pMoniker
);
632 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
635 IMoniker_Release(pMoniker
);
640 static HRESULT WINAPI
PointerMonikerCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
642 FIXME("(%d), stub!\n",fLock
);
646 static const IClassFactoryVtbl PointerMonikerCFVtbl
=
648 PointerMonikerCF_QueryInterface
,
649 PointerMonikerCF_AddRef
,
650 PointerMonikerCF_Release
,
651 PointerMonikerCF_CreateInstance
,
652 PointerMonikerCF_LockServer
654 static const IClassFactoryVtbl
*PointerMonikerCF
= &PointerMonikerCFVtbl
;
656 HRESULT
PointerMonikerCF_Create(REFIID riid
, LPVOID
*ppv
)
658 return IClassFactory_QueryInterface((IClassFactory
*)&PointerMonikerCF
, riid
, ppv
);