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 const IMonikerVtbl
* lpvtbl
; /* VTable relative to the IMoniker interface.*/
45 LONG ref
; /* reference counter for this object */
47 IUnknown
*pObject
; /* custom marshaler */
51 PointerMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
53 PointerMonikerImpl
*This
= (PointerMonikerImpl
*)iface
;
55 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
57 /* Perform a sanity check on the parameters.*/
58 if ( (This
==0) || (ppvObject
==0) )
61 /* Initialize the return parameter */
64 /* Compare the riid with the interface IDs implemented by this object.*/
65 if (IsEqualIID(&IID_IUnknown
, riid
) ||
66 IsEqualIID(&IID_IPersist
, riid
) ||
67 IsEqualIID(&IID_IPersistStream
, riid
) ||
68 IsEqualIID(&IID_IMoniker
, riid
))
71 /* Check that we obtained an interface.*/
75 /* always increase the reference count by one when it is successful */
76 IMoniker_AddRef(iface
);
81 /******************************************************************************
82 * PointerMoniker_AddRef
83 ******************************************************************************/
85 PointerMonikerImpl_AddRef(IMoniker
* iface
)
87 PointerMonikerImpl
*This
= (PointerMonikerImpl
*)iface
;
91 return InterlockedIncrement(&This
->ref
);
94 /******************************************************************************
95 * PointerMoniker_Release
96 ******************************************************************************/
98 PointerMonikerImpl_Release(IMoniker
* iface
)
100 PointerMonikerImpl
*This
= (PointerMonikerImpl
*)iface
;
103 TRACE("(%p)\n",This
);
105 ref
= InterlockedDecrement(&This
->ref
);
107 /* destroy the object if there's no more reference on it */
110 if (This
->pObject
) IUnknown_Release(This
->pObject
);
111 HeapFree(GetProcessHeap(),0,This
);
117 /******************************************************************************
118 * PointerMoniker_GetClassID
119 ******************************************************************************/
120 static HRESULT WINAPI
121 PointerMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
123 TRACE("(%p,%p)\n",iface
,pClassID
);
128 *pClassID
= CLSID_PointerMoniker
;
133 /******************************************************************************
134 * PointerMoniker_IsDirty
135 ******************************************************************************/
136 static HRESULT WINAPI
137 PointerMonikerImpl_IsDirty(IMoniker
* iface
)
139 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
140 method in the OLE-provided moniker interfaces always return S_FALSE because
141 their internal state never changes. */
143 TRACE("(%p)\n",iface
);
148 /******************************************************************************
149 * PointerMoniker_Load
150 ******************************************************************************/
151 static HRESULT WINAPI
152 PointerMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
154 TRACE("(%p)\n", pStm
);
159 /******************************************************************************
160 * PointerMoniker_Save
161 ******************************************************************************/
162 static HRESULT WINAPI
163 PointerMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
)
165 TRACE("(%p, %d)\n", pStm
, fClearDirty
);
170 /******************************************************************************
171 * PointerMoniker_GetSizeMax
174 * pcbSize [out] Pointer to size of stream needed to save object
175 ******************************************************************************/
176 static HRESULT WINAPI
177 PointerMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
)
179 TRACE("(%p,%p)\n",iface
,pcbSize
);
184 pcbSize
->u
.LowPart
= 0;
185 pcbSize
->u
.HighPart
= 0;
190 /******************************************************************************
191 * PointerMoniker_BindToObject
192 ******************************************************************************/
193 static HRESULT WINAPI
194 PointerMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
195 REFIID riid
, VOID
** ppvResult
)
197 PointerMonikerImpl
*This
= (PointerMonikerImpl
*)iface
;
199 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
204 return IUnknown_QueryInterface(This
->pObject
, riid
, ppvResult
);
207 /******************************************************************************
208 * PointerMoniker_BindToStorage
209 ******************************************************************************/
210 static HRESULT WINAPI
211 PointerMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
212 REFIID riid
, VOID
** ppvResult
)
214 PointerMonikerImpl
*This
= (PointerMonikerImpl
*)iface
;
216 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
221 return IUnknown_QueryInterface(This
->pObject
, riid
, ppvResult
);
224 /******************************************************************************
225 * PointerMoniker_Reduce
226 ******************************************************************************/
227 static HRESULT WINAPI
228 PointerMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
229 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
231 TRACE("(%p,%p,%d,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
233 if (ppmkReduced
==NULL
)
236 PointerMonikerImpl_AddRef(iface
);
240 return MK_S_REDUCED_TO_SELF
;
242 /******************************************************************************
243 * PointerMoniker_ComposeWith
244 ******************************************************************************/
245 static HRESULT WINAPI
246 PointerMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
247 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
252 IEnumMoniker
* penumMk
=0;
253 IMoniker
*pmostLeftMk
=0;
254 IMoniker
* tempMkComposite
=0;
256 TRACE("(%p,%d,%p)\n", pmkRight
, fOnlyIfNotGeneric
, ppmkComposite
);
258 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
263 IMoniker_IsSystemMoniker(pmkRight
,&mkSys
);
265 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
266 if(mkSys
==MKSYS_ANTIMONIKER
)
270 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
271 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
273 if(mkSys
==MKSYS_GENERICCOMPOSITE
){
275 res
=IMoniker_Enum(pmkRight
,TRUE
,&penumMk
);
280 res
=IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
);
282 IMoniker_IsSystemMoniker(pmostLeftMk
,&mkSys2
);
284 if(mkSys2
==MKSYS_ANTIMONIKER
){
286 IMoniker_Release(pmostLeftMk
);
288 tempMkComposite
=iface
;
289 IMoniker_AddRef(iface
);
291 while(IEnumMoniker_Next(penumMk
,1,&pmostLeftMk
,NULL
)==S_OK
){
293 res
=CreateGenericComposite(tempMkComposite
,pmostLeftMk
,ppmkComposite
);
295 IMoniker_Release(tempMkComposite
);
296 IMoniker_Release(pmostLeftMk
);
298 tempMkComposite
=*ppmkComposite
;
299 IMoniker_AddRef(tempMkComposite
);
304 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
306 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
307 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
308 a NULL moniker and a return value of MK_E_NEEDGENERIC */
310 if (!fOnlyIfNotGeneric
)
311 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
314 return MK_E_NEEDGENERIC
;
317 /******************************************************************************
318 * PointerMoniker_Enum
319 ******************************************************************************/
320 static HRESULT WINAPI
321 PointerMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
323 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
325 if (ppenumMoniker
== NULL
)
328 *ppenumMoniker
= NULL
;
333 /******************************************************************************
334 * PointerMoniker_IsEqual
335 ******************************************************************************/
336 static HRESULT WINAPI
337 PointerMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
339 PointerMonikerImpl
*This
= (PointerMonikerImpl
*)iface
;
342 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
344 if (pmkOtherMoniker
==NULL
)
347 IMoniker_IsSystemMoniker(pmkOtherMoniker
,&mkSys
);
349 if (mkSys
==MKSYS_POINTERMONIKER
)
351 PointerMonikerImpl
*pOtherMoniker
= (PointerMonikerImpl
*)pmkOtherMoniker
;
352 return This
->pObject
== pOtherMoniker
->pObject
? S_OK
: S_FALSE
;
358 /******************************************************************************
359 * PointerMoniker_Hash
360 ******************************************************************************/
361 static HRESULT WINAPI
PointerMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
363 PointerMonikerImpl
*This
= (PointerMonikerImpl
*)iface
;
368 *pdwHash
= (DWORD
)This
->pObject
;
373 /******************************************************************************
374 * PointerMoniker_IsRunning
375 ******************************************************************************/
376 static HRESULT WINAPI
377 PointerMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
378 IMoniker
* pmkNewlyRunning
)
380 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
385 /******************************************************************************
386 * PointerMoniker_GetTimeOfLastChange
387 ******************************************************************************/
388 static HRESULT WINAPI
PointerMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
393 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pAntiTime
);
397 /******************************************************************************
398 * PointerMoniker_Inverse
399 ******************************************************************************/
400 static HRESULT WINAPI
401 PointerMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
403 TRACE("(%p,%p)\n",iface
,ppmk
);
405 return CreateAntiMoniker(ppmk
);
408 /******************************************************************************
409 * PointerMoniker_CommonPrefixWith
410 ******************************************************************************/
411 static HRESULT WINAPI
412 PointerMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
414 TRACE("(%p, %p)\n", pmkOther
, ppmkPrefix
);
418 if (PointerMonikerImpl_IsEqual(iface
, pmkOther
))
420 IMoniker_AddRef(iface
);
427 return MK_E_NOPREFIX
;
430 /******************************************************************************
431 * PointerMoniker_RelativePathTo
432 ******************************************************************************/
433 static HRESULT WINAPI
434 PointerMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
)
436 TRACE("(%p,%p,%p)\n",iface
,pmOther
,ppmkRelPath
);
438 if (ppmkRelPath
==NULL
)
446 /******************************************************************************
447 * PointerMoniker_GetDisplayName
448 ******************************************************************************/
449 static HRESULT WINAPI
450 PointerMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
451 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
453 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
455 if (ppszDisplayName
==NULL
)
458 *ppszDisplayName
= NULL
;
462 /******************************************************************************
463 * PointerMoniker_ParseDisplayName
464 ******************************************************************************/
465 static HRESULT WINAPI
466 PointerMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
467 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
,
468 ULONG
* pchEaten
, IMoniker
** ppmkOut
)
470 PointerMonikerImpl
*This
= (PointerMonikerImpl
*)iface
;
472 IParseDisplayName
*pPDN
;
474 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pszDisplayName
,pchEaten
,ppmkOut
);
482 hr
= IUnknown_QueryInterface(This
->pObject
, &IID_IParseDisplayName
, (void **)&pPDN
);
486 hr
= IParseDisplayName_ParseDisplayName(pPDN
, pbc
, pszDisplayName
, pchEaten
, ppmkOut
);
487 IParseDisplayName_Release(pPDN
);
492 /******************************************************************************
493 * PointerMoniker_IsSystemMoniker
494 ******************************************************************************/
495 static HRESULT WINAPI
496 PointerMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
498 TRACE("(%p,%p)\n",iface
,pwdMksys
);
503 *pwdMksys
= MKSYS_POINTERMONIKER
;
508 /********************************************************************************/
509 /* Virtual function table for the PointerMonikerImpl class which include IPersist,*/
510 /* IPersistStream and IMoniker functions. */
511 static const IMonikerVtbl VT_PointerMonikerImpl
=
513 PointerMonikerImpl_QueryInterface
,
514 PointerMonikerImpl_AddRef
,
515 PointerMonikerImpl_Release
,
516 PointerMonikerImpl_GetClassID
,
517 PointerMonikerImpl_IsDirty
,
518 PointerMonikerImpl_Load
,
519 PointerMonikerImpl_Save
,
520 PointerMonikerImpl_GetSizeMax
,
521 PointerMonikerImpl_BindToObject
,
522 PointerMonikerImpl_BindToStorage
,
523 PointerMonikerImpl_Reduce
,
524 PointerMonikerImpl_ComposeWith
,
525 PointerMonikerImpl_Enum
,
526 PointerMonikerImpl_IsEqual
,
527 PointerMonikerImpl_Hash
,
528 PointerMonikerImpl_IsRunning
,
529 PointerMonikerImpl_GetTimeOfLastChange
,
530 PointerMonikerImpl_Inverse
,
531 PointerMonikerImpl_CommonPrefixWith
,
532 PointerMonikerImpl_RelativePathTo
,
533 PointerMonikerImpl_GetDisplayName
,
534 PointerMonikerImpl_ParseDisplayName
,
535 PointerMonikerImpl_IsSystemMoniker
538 /******************************************************************************
539 * PointerMoniker_Construct (local function)
540 *******************************************************************************/
541 static void PointerMonikerImpl_Construct(PointerMonikerImpl
* This
, IUnknown
*punk
)
543 TRACE("(%p)\n",This
);
545 /* Initialize the virtual fgunction table. */
546 This
->lpvtbl
= &VT_PointerMonikerImpl
;
549 IUnknown_AddRef(punk
);
550 This
->pObject
= punk
;
553 /***********************************************************************
554 * CreatePointerMoniker (OLE32.@)
556 * Creates a moniker which represents a pointer.
559 * punk [I] Pointer to the object to represent.
560 * ppmk [O] Address that receives the pointer to the created moniker.
564 * Failure: Any HRESULT code.
566 HRESULT WINAPI
CreatePointerMoniker(LPUNKNOWN punk
, LPMONIKER
*ppmk
)
568 PointerMonikerImpl
*This
;
570 FIXME("(%p, %p): stub\n", punk
, ppmk
);
575 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
579 return E_OUTOFMEMORY
;
582 PointerMonikerImpl_Construct(This
, punk
);
583 *ppmk
= (IMoniker
*)&This
->lpvtbl
;
587 static HRESULT WINAPI
PointerMonikerCF_QueryInterface(LPCLASSFACTORY iface
,
588 REFIID riid
, LPVOID
*ppv
)
591 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
594 IUnknown_AddRef(iface
);
597 return E_NOINTERFACE
;
600 static ULONG WINAPI
PointerMonikerCF_AddRef(LPCLASSFACTORY iface
)
602 return 2; /* non-heap based object */
605 static ULONG WINAPI
PointerMonikerCF_Release(LPCLASSFACTORY iface
)
607 return 1; /* non-heap based object */
610 static HRESULT WINAPI
PointerMonikerCF_CreateInstance(LPCLASSFACTORY iface
,
611 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
616 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
621 return CLASS_E_NOAGGREGATION
;
623 hr
= CreatePointerMoniker(NULL
, &pMoniker
);
627 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
630 IMoniker_Release(pMoniker
);
635 static HRESULT WINAPI
PointerMonikerCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
637 FIXME("(%d), stub!\n",fLock
);
641 static const IClassFactoryVtbl PointerMonikerCFVtbl
=
643 PointerMonikerCF_QueryInterface
,
644 PointerMonikerCF_AddRef
,
645 PointerMonikerCF_Release
,
646 PointerMonikerCF_CreateInstance
,
647 PointerMonikerCF_LockServer
649 static const IClassFactoryVtbl
*PointerMonikerCF
= &PointerMonikerCFVtbl
;
651 HRESULT
PointerMonikerCF_Create(REFIID riid
, LPVOID
*ppv
)
653 return IClassFactory_QueryInterface((IClassFactory
*)&PointerMonikerCF
, riid
, ppv
);