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
34 #include "wine/debug.h"
35 #include "wine/heap.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
40 /* PointerMoniker data structure */
41 typedef struct PointerMonikerImpl
43 IMoniker IMoniker_iface
;
44 IMarshal IMarshal_iface
;
51 static inline PointerMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
53 return CONTAINING_RECORD(iface
, PointerMonikerImpl
, IMoniker_iface
);
56 static PointerMonikerImpl
*impl_from_IMarshal(IMarshal
*iface
)
58 return CONTAINING_RECORD(iface
, PointerMonikerImpl
, IMarshal_iface
);
61 static PointerMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
);
63 static HRESULT WINAPI
PointerMonikerImpl_QueryInterface(IMoniker
*iface
, REFIID riid
, void **ppvObject
)
65 PointerMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
67 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppvObject
);
74 if (IsEqualIID(&IID_IUnknown
, riid
) ||
75 IsEqualIID(&IID_IPersist
, riid
) ||
76 IsEqualIID(&IID_IPersistStream
, riid
) ||
77 IsEqualIID(&IID_IMoniker
, riid
) ||
78 IsEqualGUID(&CLSID_PointerMoniker
, riid
))
82 else if (IsEqualIID(&IID_IMarshal
, riid
))
83 *ppvObject
= &moniker
->IMarshal_iface
;
88 IMoniker_AddRef(iface
);
93 static ULONG WINAPI
PointerMonikerImpl_AddRef(IMoniker
*iface
)
95 PointerMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
96 ULONG refcount
= InterlockedIncrement(&moniker
->refcount
);
98 TRACE("%p, refcount %u.\n", iface
, refcount
);
103 static ULONG WINAPI
PointerMonikerImpl_Release(IMoniker
*iface
)
105 PointerMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
106 ULONG refcount
= InterlockedDecrement(&moniker
->refcount
);
108 TRACE("%p, refcount %u.\n", iface
, refcount
);
112 if (moniker
->pObject
) IUnknown_Release(moniker
->pObject
);
119 /******************************************************************************
120 * PointerMoniker_GetClassID
121 ******************************************************************************/
122 static HRESULT WINAPI
123 PointerMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
125 TRACE("(%p,%p)\n",iface
,pClassID
);
130 *pClassID
= CLSID_PointerMoniker
;
135 /******************************************************************************
136 * PointerMoniker_IsDirty
137 ******************************************************************************/
138 static HRESULT WINAPI
139 PointerMonikerImpl_IsDirty(IMoniker
* iface
)
141 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
142 method in the OLE-provided moniker interfaces always return S_FALSE because
143 their internal state never changes. */
145 TRACE("(%p)\n",iface
);
150 /******************************************************************************
151 * PointerMoniker_Load
152 ******************************************************************************/
153 static HRESULT WINAPI
154 PointerMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
156 TRACE("(%p)\n", pStm
);
161 /******************************************************************************
162 * PointerMoniker_Save
163 ******************************************************************************/
164 static HRESULT WINAPI
165 PointerMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
)
167 TRACE("(%p, %d)\n", pStm
, fClearDirty
);
172 /******************************************************************************
173 * PointerMoniker_GetSizeMax
176 * pcbSize [out] Pointer to size of stream needed to save object
177 ******************************************************************************/
178 static HRESULT WINAPI
179 PointerMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
)
181 TRACE("(%p,%p)\n",iface
,pcbSize
);
186 pcbSize
->u
.LowPart
= 0;
187 pcbSize
->u
.HighPart
= 0;
192 /******************************************************************************
193 * PointerMoniker_BindToObject
194 ******************************************************************************/
195 static HRESULT WINAPI
196 PointerMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
197 REFIID riid
, VOID
** ppvResult
)
199 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
201 TRACE("(%p,%p,%p,%s,%p)\n",iface
,pbc
,pmkToLeft
,debugstr_guid(riid
),ppvResult
);
206 return IUnknown_QueryInterface(This
->pObject
, riid
, ppvResult
);
209 /******************************************************************************
210 * PointerMoniker_BindToStorage
211 ******************************************************************************/
212 static HRESULT WINAPI
213 PointerMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
214 REFIID riid
, VOID
** ppvResult
)
216 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
218 TRACE("(%p,%p,%p,%s,%p)\n",iface
,pbc
,pmkToLeft
,debugstr_guid(riid
),ppvResult
);
223 return IUnknown_QueryInterface(This
->pObject
, riid
, ppvResult
);
226 /******************************************************************************
227 * PointerMoniker_Reduce
228 ******************************************************************************/
229 static HRESULT WINAPI
230 PointerMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
231 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
233 TRACE("(%p,%p,%d,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
235 if (ppmkReduced
==NULL
)
238 PointerMonikerImpl_AddRef(iface
);
242 return MK_S_REDUCED_TO_SELF
;
244 /******************************************************************************
245 * PointerMoniker_ComposeWith
246 ******************************************************************************/
247 static HRESULT WINAPI
248 PointerMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
249 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
253 DWORD mkSys
,mkSys2
, order
;
254 IEnumMoniker
* penumMk
=0;
255 IMoniker
*pmostLeftMk
=0;
256 IMoniker
* tempMkComposite
=0;
258 TRACE("(%p,%d,%p)\n", pmkRight
, fOnlyIfNotGeneric
, ppmkComposite
);
260 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
265 if (is_anti_moniker(pmkRight
, &order
))
267 return order
> 1 ? create_anti_moniker(order
- 1, ppmkComposite
) : S_OK
;
271 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
272 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
273 IMoniker_IsSystemMoniker(pmkRight
,&mkSys
);
275 if(mkSys
==MKSYS_GENERICCOMPOSITE
){
277 res
=IMoniker_Enum(pmkRight
,TRUE
,&penumMk
);
282 res
=IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
);
284 IMoniker_IsSystemMoniker(pmostLeftMk
,&mkSys2
);
286 if(mkSys2
==MKSYS_ANTIMONIKER
){
288 IMoniker_Release(pmostLeftMk
);
290 tempMkComposite
=iface
;
291 IMoniker_AddRef(iface
);
293 while(IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
)==S_OK
){
295 res
=CreateGenericComposite(tempMkComposite
,pmostLeftMk
,ppmkComposite
);
297 IMoniker_Release(tempMkComposite
);
298 IMoniker_Release(pmostLeftMk
);
300 tempMkComposite
=*ppmkComposite
;
301 IMoniker_AddRef(tempMkComposite
);
306 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
308 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
309 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
310 a NULL moniker and a return value of MK_E_NEEDGENERIC */
312 if (!fOnlyIfNotGeneric
)
313 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
316 return MK_E_NEEDGENERIC
;
320 /******************************************************************************
321 * PointerMoniker_Enum
322 ******************************************************************************/
323 static HRESULT WINAPI
PointerMonikerImpl_Enum(IMoniker
*iface
, BOOL fForward
, IEnumMoniker
**ppenumMoniker
)
325 TRACE("%p, %d, %p.\n", iface
, fForward
, ppenumMoniker
);
330 *ppenumMoniker
= NULL
;
335 /******************************************************************************
336 * PointerMoniker_IsEqual
337 ******************************************************************************/
338 static HRESULT WINAPI
PointerMonikerImpl_IsEqual(IMoniker
*iface
, IMoniker
*other
)
340 PointerMonikerImpl
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
342 TRACE("%p, %p.\n", iface
, other
);
347 other_moniker
= unsafe_impl_from_IMoniker(other
);
351 return moniker
->pObject
== other_moniker
->pObject
? S_OK
: S_FALSE
;
354 /******************************************************************************
355 * PointerMoniker_Hash
356 ******************************************************************************/
357 static HRESULT WINAPI
PointerMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
359 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
364 *pdwHash
= PtrToUlong(This
->pObject
);
369 /******************************************************************************
370 * PointerMoniker_IsRunning
371 ******************************************************************************/
372 static HRESULT WINAPI
373 PointerMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
374 IMoniker
* pmkNewlyRunning
)
376 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
381 /******************************************************************************
382 * PointerMoniker_GetTimeOfLastChange
383 ******************************************************************************/
384 static HRESULT WINAPI
PointerMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
389 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pAntiTime
);
393 /******************************************************************************
394 * PointerMoniker_Inverse
395 ******************************************************************************/
396 static HRESULT WINAPI
397 PointerMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
399 TRACE("(%p,%p)\n",iface
,ppmk
);
401 return CreateAntiMoniker(ppmk
);
404 /******************************************************************************
405 * PointerMoniker_CommonPrefixWith
406 ******************************************************************************/
407 static HRESULT WINAPI
PointerMonikerImpl_CommonPrefixWith(IMoniker
*iface
, IMoniker
*other
, IMoniker
**prefix
)
409 TRACE("%p, %p, %p.\n", iface
, other
, prefix
);
411 if (!prefix
|| !other
)
416 if (PointerMonikerImpl_IsEqual(iface
, other
) == S_OK
)
418 IMoniker_AddRef(iface
);
425 return MK_E_NOPREFIX
;
428 /******************************************************************************
429 * PointerMoniker_RelativePathTo
430 ******************************************************************************/
431 static HRESULT WINAPI
432 PointerMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
)
434 TRACE("(%p,%p,%p)\n",iface
,pmOther
,ppmkRelPath
);
436 if (ppmkRelPath
==NULL
)
444 /******************************************************************************
445 * PointerMoniker_GetDisplayName
446 ******************************************************************************/
447 static HRESULT WINAPI
448 PointerMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
449 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
451 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
453 if (ppszDisplayName
==NULL
)
456 *ppszDisplayName
= NULL
;
460 /******************************************************************************
461 * PointerMoniker_ParseDisplayName
462 ******************************************************************************/
463 static HRESULT WINAPI
464 PointerMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
465 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
,
466 ULONG
* pchEaten
, IMoniker
** ppmkOut
)
468 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
470 IParseDisplayName
*pPDN
;
472 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pszDisplayName
,pchEaten
,ppmkOut
);
480 hr
= IUnknown_QueryInterface(This
->pObject
, &IID_IParseDisplayName
, (void **)&pPDN
);
484 hr
= IParseDisplayName_ParseDisplayName(pPDN
, pbc
, pszDisplayName
, pchEaten
, ppmkOut
);
485 IParseDisplayName_Release(pPDN
);
490 /******************************************************************************
491 * PointerMoniker_IsSystemMoniker
492 ******************************************************************************/
493 static HRESULT WINAPI
494 PointerMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
496 TRACE("(%p,%p)\n",iface
,pwdMksys
);
501 *pwdMksys
= MKSYS_POINTERMONIKER
;
506 /********************************************************************************/
507 /* Virtual function table for the PointerMonikerImpl class which include IPersist,*/
508 /* IPersistStream and IMoniker functions. */
509 static const IMonikerVtbl VT_PointerMonikerImpl
=
511 PointerMonikerImpl_QueryInterface
,
512 PointerMonikerImpl_AddRef
,
513 PointerMonikerImpl_Release
,
514 PointerMonikerImpl_GetClassID
,
515 PointerMonikerImpl_IsDirty
,
516 PointerMonikerImpl_Load
,
517 PointerMonikerImpl_Save
,
518 PointerMonikerImpl_GetSizeMax
,
519 PointerMonikerImpl_BindToObject
,
520 PointerMonikerImpl_BindToStorage
,
521 PointerMonikerImpl_Reduce
,
522 PointerMonikerImpl_ComposeWith
,
523 PointerMonikerImpl_Enum
,
524 PointerMonikerImpl_IsEqual
,
525 PointerMonikerImpl_Hash
,
526 PointerMonikerImpl_IsRunning
,
527 PointerMonikerImpl_GetTimeOfLastChange
,
528 PointerMonikerImpl_Inverse
,
529 PointerMonikerImpl_CommonPrefixWith
,
530 PointerMonikerImpl_RelativePathTo
,
531 PointerMonikerImpl_GetDisplayName
,
532 PointerMonikerImpl_ParseDisplayName
,
533 PointerMonikerImpl_IsSystemMoniker
536 static PointerMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
)
538 if (iface
->lpVtbl
!= &VT_PointerMonikerImpl
)
540 return CONTAINING_RECORD(iface
, PointerMonikerImpl
, IMoniker_iface
);
543 static HRESULT WINAPI
pointer_moniker_marshal_QueryInterface(IMarshal
*iface
, REFIID riid
, LPVOID
*ppv
)
545 PointerMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
547 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
549 return IMoniker_QueryInterface(&moniker
->IMoniker_iface
, riid
, ppv
);
552 static ULONG WINAPI
pointer_moniker_marshal_AddRef(IMarshal
*iface
)
554 PointerMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
556 TRACE("%p.\n",iface
);
558 return IMoniker_AddRef(&moniker
->IMoniker_iface
);
561 static ULONG WINAPI
pointer_moniker_marshal_Release(IMarshal
*iface
)
563 PointerMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
565 TRACE("%p.\n",iface
);
567 return IMoniker_Release(&moniker
->IMoniker_iface
);
570 static HRESULT WINAPI
pointer_moniker_marshal_GetUnmarshalClass(IMarshal
*iface
, REFIID riid
, void *pv
,
571 DWORD dwDestContext
, void *pvDestContext
, DWORD mshlflags
, CLSID
*clsid
)
573 PointerMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
575 TRACE("%p, %s, %p, %x, %p, %x, %p.\n", iface
, debugstr_guid(riid
), pv
, dwDestContext
, pvDestContext
,
578 return IMoniker_GetClassID(&moniker
->IMoniker_iface
, clsid
);
581 static HRESULT WINAPI
pointer_moniker_marshal_GetMarshalSizeMax(IMarshal
*iface
, REFIID riid
, void *pv
,
582 DWORD dwDestContext
, void *pvDestContext
, DWORD mshlflags
, DWORD
*size
)
584 PointerMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
586 TRACE("%p, %s, %p, %d, %p, %#x, %p.\n", iface
, debugstr_guid(riid
), pv
, dwDestContext
, pvDestContext
,
589 return CoGetMarshalSizeMax(size
, &IID_IUnknown
, moniker
->pObject
, dwDestContext
, pvDestContext
, mshlflags
);
592 static HRESULT WINAPI
pointer_moniker_marshal_MarshalInterface(IMarshal
*iface
, IStream
*stream
, REFIID riid
,
593 void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD mshlflags
)
595 PointerMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
597 TRACE("%p, %s, %p, %x, %p, %x.\n", stream
, debugstr_guid(riid
), pv
,
598 dwDestContext
, pvDestContext
, mshlflags
);
600 return CoMarshalInterface(stream
, &IID_IUnknown
, moniker
->pObject
, dwDestContext
,
601 pvDestContext
, mshlflags
);
604 static HRESULT WINAPI
pointer_moniker_marshal_UnmarshalInterface(IMarshal
*iface
, IStream
*stream
,
605 REFIID riid
, void **ppv
)
607 PointerMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
611 TRACE("%p, %p, %s, %p.\n", iface
, stream
, debugstr_guid(riid
), ppv
);
613 hr
= CoUnmarshalInterface(stream
, &IID_IUnknown
, (void **)&object
);
616 ERR("Couldn't unmarshal moniker, hr = %#x.\n", hr
);
620 if (moniker
->pObject
)
621 IUnknown_Release(moniker
->pObject
);
622 moniker
->pObject
= object
;
624 return IMoniker_QueryInterface(&moniker
->IMoniker_iface
, riid
, ppv
);
627 static HRESULT WINAPI
pointer_moniker_marshal_ReleaseMarshalData(IMarshal
*iface
, IStream
*stream
)
629 TRACE("%p, %p.\n", iface
, stream
);
634 static HRESULT WINAPI
pointer_moniker_marshal_DisconnectObject(IMarshal
*iface
, DWORD reserved
)
636 TRACE("%p, %#x.\n", iface
, reserved
);
641 static const IMarshalVtbl pointer_moniker_marshal_vtbl
=
643 pointer_moniker_marshal_QueryInterface
,
644 pointer_moniker_marshal_AddRef
,
645 pointer_moniker_marshal_Release
,
646 pointer_moniker_marshal_GetUnmarshalClass
,
647 pointer_moniker_marshal_GetMarshalSizeMax
,
648 pointer_moniker_marshal_MarshalInterface
,
649 pointer_moniker_marshal_UnmarshalInterface
,
650 pointer_moniker_marshal_ReleaseMarshalData
,
651 pointer_moniker_marshal_DisconnectObject
654 /***********************************************************************
655 * CreatePointerMoniker (OLE32.@)
657 HRESULT WINAPI
CreatePointerMoniker(IUnknown
*object
, IMoniker
**ret
)
659 PointerMonikerImpl
*moniker
;
661 TRACE("(%p, %p)\n", object
, ret
);
666 moniker
= heap_alloc(sizeof(*moniker
));
670 return E_OUTOFMEMORY
;
673 moniker
->IMoniker_iface
.lpVtbl
= &VT_PointerMonikerImpl
;
674 moniker
->IMarshal_iface
.lpVtbl
= &pointer_moniker_marshal_vtbl
;
675 moniker
->refcount
= 1;
676 moniker
->pObject
= object
;
677 if (moniker
->pObject
)
678 IUnknown_AddRef(moniker
->pObject
);
680 *ret
= &moniker
->IMoniker_iface
;
685 HRESULT WINAPI
PointerMoniker_CreateInstance(IClassFactory
*iface
,
686 IUnknown
*pUnk
, REFIID riid
, void **ppv
)
691 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
696 return CLASS_E_NOAGGREGATION
;
698 hr
= CreatePointerMoniker(NULL
, &pMoniker
);
702 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
703 IMoniker_Release(pMoniker
);