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
22 #define WIN32_NO_STATUS
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
34 //#include "winerror.h"
35 //#include "winuser.h"
38 #include <wine/debug.h>
41 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
43 /* PointerMoniker data structure */
44 typedef struct PointerMonikerImpl
{
46 IMoniker IMoniker_iface
;
48 LONG ref
; /* reference counter for this object */
50 IUnknown
*pObject
; /* custom marshaler */
53 static inline PointerMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
55 return CONTAINING_RECORD(iface
, PointerMonikerImpl
, IMoniker_iface
);
59 PointerMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
61 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
63 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
65 /* Perform a sanity check on the parameters.*/
66 if ( (This
==0) || (ppvObject
==0) )
69 /* Initialize the return parameter */
72 /* Compare the riid with the interface IDs implemented by this object.*/
73 if (IsEqualIID(&IID_IUnknown
, riid
) ||
74 IsEqualIID(&IID_IPersist
, riid
) ||
75 IsEqualIID(&IID_IPersistStream
, riid
) ||
76 IsEqualIID(&IID_IMoniker
, riid
))
79 /* Check that we obtained an interface.*/
83 /* always increase the reference count by one when it is successful */
84 IMoniker_AddRef(iface
);
89 /******************************************************************************
90 * PointerMoniker_AddRef
91 ******************************************************************************/
93 PointerMonikerImpl_AddRef(IMoniker
* iface
)
95 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
99 return InterlockedIncrement(&This
->ref
);
102 /******************************************************************************
103 * PointerMoniker_Release
104 ******************************************************************************/
106 PointerMonikerImpl_Release(IMoniker
* iface
)
108 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
111 TRACE("(%p)\n",This
);
113 ref
= InterlockedDecrement(&This
->ref
);
115 /* destroy the object if there's no more reference on it */
118 if (This
->pObject
) IUnknown_Release(This
->pObject
);
119 HeapFree(GetProcessHeap(),0,This
);
125 /******************************************************************************
126 * PointerMoniker_GetClassID
127 ******************************************************************************/
128 static HRESULT WINAPI
129 PointerMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
131 TRACE("(%p,%p)\n",iface
,pClassID
);
136 *pClassID
= CLSID_PointerMoniker
;
141 /******************************************************************************
142 * PointerMoniker_IsDirty
143 ******************************************************************************/
144 static HRESULT WINAPI
145 PointerMonikerImpl_IsDirty(IMoniker
* iface
)
147 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
148 method in the OLE-provided moniker interfaces always return S_FALSE because
149 their internal state never changes. */
151 TRACE("(%p)\n",iface
);
156 /******************************************************************************
157 * PointerMoniker_Load
158 ******************************************************************************/
159 static HRESULT WINAPI
160 PointerMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
162 TRACE("(%p)\n", pStm
);
167 /******************************************************************************
168 * PointerMoniker_Save
169 ******************************************************************************/
170 static HRESULT WINAPI
171 PointerMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
)
173 TRACE("(%p, %d)\n", pStm
, fClearDirty
);
178 /******************************************************************************
179 * PointerMoniker_GetSizeMax
182 * pcbSize [out] Pointer to size of stream needed to save object
183 ******************************************************************************/
184 static HRESULT WINAPI
185 PointerMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
)
187 TRACE("(%p,%p)\n",iface
,pcbSize
);
192 pcbSize
->u
.LowPart
= 0;
193 pcbSize
->u
.HighPart
= 0;
198 /******************************************************************************
199 * PointerMoniker_BindToObject
200 ******************************************************************************/
201 static HRESULT WINAPI
202 PointerMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
203 REFIID riid
, VOID
** ppvResult
)
205 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
207 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
212 return IUnknown_QueryInterface(This
->pObject
, riid
, ppvResult
);
215 /******************************************************************************
216 * PointerMoniker_BindToStorage
217 ******************************************************************************/
218 static HRESULT WINAPI
219 PointerMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
220 REFIID riid
, VOID
** ppvResult
)
222 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
224 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
229 return IUnknown_QueryInterface(This
->pObject
, riid
, ppvResult
);
232 /******************************************************************************
233 * PointerMoniker_Reduce
234 ******************************************************************************/
235 static HRESULT WINAPI
236 PointerMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
237 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
239 TRACE("(%p,%p,%d,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
241 if (ppmkReduced
==NULL
)
244 PointerMonikerImpl_AddRef(iface
);
248 return MK_S_REDUCED_TO_SELF
;
250 /******************************************************************************
251 * PointerMoniker_ComposeWith
252 ******************************************************************************/
253 static HRESULT WINAPI
254 PointerMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
255 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
260 IEnumMoniker
* penumMk
=0;
261 IMoniker
*pmostLeftMk
=0;
262 IMoniker
* tempMkComposite
=0;
264 TRACE("(%p,%d,%p)\n", pmkRight
, fOnlyIfNotGeneric
, ppmkComposite
);
266 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
271 IMoniker_IsSystemMoniker(pmkRight
,&mkSys
);
273 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
274 if(mkSys
==MKSYS_ANTIMONIKER
)
278 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
279 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
281 if(mkSys
==MKSYS_GENERICCOMPOSITE
){
283 res
=IMoniker_Enum(pmkRight
,TRUE
,&penumMk
);
288 res
=IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
);
290 IMoniker_IsSystemMoniker(pmostLeftMk
,&mkSys2
);
292 if(mkSys2
==MKSYS_ANTIMONIKER
){
294 IMoniker_Release(pmostLeftMk
);
296 tempMkComposite
=iface
;
297 IMoniker_AddRef(iface
);
299 while(IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
)==S_OK
){
301 res
=CreateGenericComposite(tempMkComposite
,pmostLeftMk
,ppmkComposite
);
303 IMoniker_Release(tempMkComposite
);
304 IMoniker_Release(pmostLeftMk
);
306 tempMkComposite
=*ppmkComposite
;
307 IMoniker_AddRef(tempMkComposite
);
312 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
314 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
315 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
316 a NULL moniker and a return value of MK_E_NEEDGENERIC */
318 if (!fOnlyIfNotGeneric
)
319 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
322 return MK_E_NEEDGENERIC
;
325 /******************************************************************************
326 * PointerMoniker_Enum
327 ******************************************************************************/
328 static HRESULT WINAPI
329 PointerMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
331 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
333 if (ppenumMoniker
== NULL
)
336 *ppenumMoniker
= NULL
;
341 /******************************************************************************
342 * PointerMoniker_IsEqual
343 ******************************************************************************/
344 static HRESULT WINAPI
345 PointerMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
347 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
350 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
352 if (pmkOtherMoniker
==NULL
)
355 IMoniker_IsSystemMoniker(pmkOtherMoniker
,&mkSys
);
357 if (mkSys
==MKSYS_POINTERMONIKER
)
359 PointerMonikerImpl
*pOtherMoniker
= impl_from_IMoniker(pmkOtherMoniker
);
360 return This
->pObject
== pOtherMoniker
->pObject
? S_OK
: S_FALSE
;
366 /******************************************************************************
367 * PointerMoniker_Hash
368 ******************************************************************************/
369 static HRESULT WINAPI
PointerMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
371 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
376 *pdwHash
= PtrToUlong(This
->pObject
);
381 /******************************************************************************
382 * PointerMoniker_IsRunning
383 ******************************************************************************/
384 static HRESULT WINAPI
385 PointerMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
386 IMoniker
* pmkNewlyRunning
)
388 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
393 /******************************************************************************
394 * PointerMoniker_GetTimeOfLastChange
395 ******************************************************************************/
396 static HRESULT WINAPI
PointerMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
401 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pAntiTime
);
405 /******************************************************************************
406 * PointerMoniker_Inverse
407 ******************************************************************************/
408 static HRESULT WINAPI
409 PointerMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
411 TRACE("(%p,%p)\n",iface
,ppmk
);
413 return CreateAntiMoniker(ppmk
);
416 /******************************************************************************
417 * PointerMoniker_CommonPrefixWith
418 ******************************************************************************/
419 static HRESULT WINAPI
420 PointerMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
422 TRACE("(%p, %p)\n", pmkOther
, ppmkPrefix
);
426 if (PointerMonikerImpl_IsEqual(iface
, pmkOther
))
428 IMoniker_AddRef(iface
);
435 return MK_E_NOPREFIX
;
438 /******************************************************************************
439 * PointerMoniker_RelativePathTo
440 ******************************************************************************/
441 static HRESULT WINAPI
442 PointerMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
)
444 TRACE("(%p,%p,%p)\n",iface
,pmOther
,ppmkRelPath
);
446 if (ppmkRelPath
==NULL
)
454 /******************************************************************************
455 * PointerMoniker_GetDisplayName
456 ******************************************************************************/
457 static HRESULT WINAPI
458 PointerMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
459 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
461 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
463 if (ppszDisplayName
==NULL
)
466 *ppszDisplayName
= NULL
;
470 /******************************************************************************
471 * PointerMoniker_ParseDisplayName
472 ******************************************************************************/
473 static HRESULT WINAPI
474 PointerMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
475 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
,
476 ULONG
* pchEaten
, IMoniker
** ppmkOut
)
478 PointerMonikerImpl
*This
= impl_from_IMoniker(iface
);
480 IParseDisplayName
*pPDN
;
482 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pszDisplayName
,pchEaten
,ppmkOut
);
490 hr
= IUnknown_QueryInterface(This
->pObject
, &IID_IParseDisplayName
, (void **)&pPDN
);
494 hr
= IParseDisplayName_ParseDisplayName(pPDN
, pbc
, pszDisplayName
, pchEaten
, ppmkOut
);
495 IParseDisplayName_Release(pPDN
);
500 /******************************************************************************
501 * PointerMoniker_IsSystemMoniker
502 ******************************************************************************/
503 static HRESULT WINAPI
504 PointerMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
506 TRACE("(%p,%p)\n",iface
,pwdMksys
);
511 *pwdMksys
= MKSYS_POINTERMONIKER
;
516 /********************************************************************************/
517 /* Virtual function table for the PointerMonikerImpl class which include IPersist,*/
518 /* IPersistStream and IMoniker functions. */
519 static const IMonikerVtbl VT_PointerMonikerImpl
=
521 PointerMonikerImpl_QueryInterface
,
522 PointerMonikerImpl_AddRef
,
523 PointerMonikerImpl_Release
,
524 PointerMonikerImpl_GetClassID
,
525 PointerMonikerImpl_IsDirty
,
526 PointerMonikerImpl_Load
,
527 PointerMonikerImpl_Save
,
528 PointerMonikerImpl_GetSizeMax
,
529 PointerMonikerImpl_BindToObject
,
530 PointerMonikerImpl_BindToStorage
,
531 PointerMonikerImpl_Reduce
,
532 PointerMonikerImpl_ComposeWith
,
533 PointerMonikerImpl_Enum
,
534 PointerMonikerImpl_IsEqual
,
535 PointerMonikerImpl_Hash
,
536 PointerMonikerImpl_IsRunning
,
537 PointerMonikerImpl_GetTimeOfLastChange
,
538 PointerMonikerImpl_Inverse
,
539 PointerMonikerImpl_CommonPrefixWith
,
540 PointerMonikerImpl_RelativePathTo
,
541 PointerMonikerImpl_GetDisplayName
,
542 PointerMonikerImpl_ParseDisplayName
,
543 PointerMonikerImpl_IsSystemMoniker
546 /******************************************************************************
547 * PointerMoniker_Construct (local function)
548 *******************************************************************************/
549 static void PointerMonikerImpl_Construct(PointerMonikerImpl
* This
, IUnknown
*punk
)
551 TRACE("(%p)\n",This
);
553 /* Initialize the virtual function table. */
554 This
->IMoniker_iface
.lpVtbl
= &VT_PointerMonikerImpl
;
557 IUnknown_AddRef(punk
);
558 This
->pObject
= punk
;
561 /***********************************************************************
562 * CreatePointerMoniker (OLE32.@)
564 * Creates a moniker which represents a pointer.
567 * punk [I] Pointer to the object to represent.
568 * ppmk [O] Address that receives the pointer to the created moniker.
572 * Failure: Any HRESULT code.
574 HRESULT WINAPI
CreatePointerMoniker(LPUNKNOWN punk
, LPMONIKER
*ppmk
)
576 PointerMonikerImpl
*This
;
578 TRACE("(%p, %p)\n", punk
, ppmk
);
583 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
587 return E_OUTOFMEMORY
;
590 PointerMonikerImpl_Construct(This
, punk
);
591 *ppmk
= &This
->IMoniker_iface
;
595 static HRESULT WINAPI
PointerMonikerCF_QueryInterface(LPCLASSFACTORY iface
,
596 REFIID riid
, LPVOID
*ppv
)
599 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
602 IClassFactory_AddRef(iface
);
605 return E_NOINTERFACE
;
608 static ULONG WINAPI
PointerMonikerCF_AddRef(LPCLASSFACTORY iface
)
610 return 2; /* non-heap based object */
613 static ULONG WINAPI
PointerMonikerCF_Release(LPCLASSFACTORY iface
)
615 return 1; /* non-heap based object */
618 static HRESULT WINAPI
PointerMonikerCF_CreateInstance(LPCLASSFACTORY iface
,
619 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
624 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
629 return CLASS_E_NOAGGREGATION
;
631 hr
= CreatePointerMoniker(NULL
, &pMoniker
);
635 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
638 IMoniker_Release(pMoniker
);
643 static HRESULT WINAPI
PointerMonikerCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
645 FIXME("(%d), stub!\n",fLock
);
649 static const IClassFactoryVtbl PointerMonikerCFVtbl
=
651 PointerMonikerCF_QueryInterface
,
652 PointerMonikerCF_AddRef
,
653 PointerMonikerCF_Release
,
654 PointerMonikerCF_CreateInstance
,
655 PointerMonikerCF_LockServer
657 static const IClassFactoryVtbl
*PointerMonikerCF
= &PointerMonikerCFVtbl
;
659 HRESULT
PointerMonikerCF_Create(REFIID riid
, LPVOID
*ppv
)
661 return IClassFactory_QueryInterface((IClassFactory
*)&PointerMonikerCF
, riid
, ppv
);