xref: /reactos/dll/win32/ole32/pointermoniker.c (revision c2c66aff)
1 /*
2  * Pointer Moniker Implementation
3  *
4  * Copyright 1999 Noomen Hamza
5  * Copyright 2008 Robert Shearman (for CodeWeavers)
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 #include "precomp.h"
23 
24 WINE_DEFAULT_DEBUG_CHANNEL(ole);
25 
26 /* PointerMoniker data structure */
27 typedef struct PointerMonikerImpl{
28 
29     IMoniker IMoniker_iface;
30 
31     LONG ref; /* reference counter for this object */
32 
33     IUnknown *pObject; /* custom marshaler */
34 } PointerMonikerImpl;
35 
36 static inline PointerMonikerImpl *impl_from_IMoniker(IMoniker *iface)
37 {
38 return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface);
39 }
40 
41 static HRESULT WINAPI
42 PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
43 {
44     PointerMonikerImpl *This = impl_from_IMoniker(iface);
45 
46     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
47 
48     /* Perform a sanity check on the parameters.*/
49     if ( (This==0) || (ppvObject==0) )
50 	return E_INVALIDARG;
51 
52     /* Initialize the return parameter */
53     *ppvObject = 0;
54 
55     /* Compare the riid with the interface IDs implemented by this object.*/
56     if (IsEqualIID(&IID_IUnknown, riid) ||
57         IsEqualIID(&IID_IPersist, riid) ||
58         IsEqualIID(&IID_IPersistStream, riid) ||
59         IsEqualIID(&IID_IMoniker, riid))
60         *ppvObject = iface;
61 
62     /* Check that we obtained an interface.*/
63     if ((*ppvObject)==0)
64         return E_NOINTERFACE;
65 
66     /* always increase the reference count by one when it is successful */
67     IMoniker_AddRef(iface);
68 
69     return S_OK;
70 }
71 
72 /******************************************************************************
73  *        PointerMoniker_AddRef
74  ******************************************************************************/
75 static ULONG WINAPI
76 PointerMonikerImpl_AddRef(IMoniker* iface)
77 {
78     PointerMonikerImpl *This = impl_from_IMoniker(iface);
79 
80     TRACE("(%p)\n",This);
81 
82     return InterlockedIncrement(&This->ref);
83 }
84 
85 /******************************************************************************
86  *        PointerMoniker_Release
87  ******************************************************************************/
88 static ULONG WINAPI
89 PointerMonikerImpl_Release(IMoniker* iface)
90 {
91     PointerMonikerImpl *This = impl_from_IMoniker(iface);
92     ULONG ref;
93 
94     TRACE("(%p)\n",This);
95 
96     ref = InterlockedDecrement(&This->ref);
97 
98     /* destroy the object if there are no more references on it */
99     if (ref == 0)
100     {
101         if (This->pObject) IUnknown_Release(This->pObject);
102         HeapFree(GetProcessHeap(),0,This);
103     }
104 
105     return ref;
106 }
107 
108 /******************************************************************************
109  *        PointerMoniker_GetClassID
110  ******************************************************************************/
111 static HRESULT WINAPI
112 PointerMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
113 {
114     TRACE("(%p,%p)\n",iface,pClassID);
115 
116     if (pClassID==NULL)
117         return E_POINTER;
118 
119     *pClassID = CLSID_PointerMoniker;
120 
121     return S_OK;
122 }
123 
124 /******************************************************************************
125  *        PointerMoniker_IsDirty
126  ******************************************************************************/
127 static HRESULT WINAPI
128 PointerMonikerImpl_IsDirty(IMoniker* iface)
129 {
130     /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
131        method in the OLE-provided moniker interfaces always return S_FALSE because
132        their internal state never changes. */
133 
134     TRACE("(%p)\n",iface);
135 
136     return S_FALSE;
137 }
138 
139 /******************************************************************************
140  *        PointerMoniker_Load
141  ******************************************************************************/
142 static HRESULT WINAPI
143 PointerMonikerImpl_Load(IMoniker* iface,IStream* pStm)
144 {
145     TRACE("(%p)\n", pStm);
146 
147     return E_NOTIMPL;
148 }
149 
150 /******************************************************************************
151  *        PointerMoniker_Save
152  ******************************************************************************/
153 static HRESULT WINAPI
154 PointerMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
155 {
156     TRACE("(%p, %d)\n", pStm, fClearDirty);
157 
158     return E_NOTIMPL;
159 }
160 
161 /******************************************************************************
162  *        PointerMoniker_GetSizeMax
163  *
164  * PARAMS
165  * pcbSize [out] Pointer to size of stream needed to save object
166  ******************************************************************************/
167 static HRESULT WINAPI
168 PointerMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
169 {
170     TRACE("(%p,%p)\n",iface,pcbSize);
171 
172     if (!pcbSize)
173         return E_POINTER;
174 
175     pcbSize->u.LowPart = 0;
176     pcbSize->u.HighPart = 0;
177 
178     return E_NOTIMPL;
179 }
180 
181 /******************************************************************************
182  *                  PointerMoniker_BindToObject
183  ******************************************************************************/
184 static HRESULT WINAPI
185 PointerMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
186                              REFIID riid, VOID** ppvResult)
187 {
188     PointerMonikerImpl *This = impl_from_IMoniker(iface);
189 
190     TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
191 
192     if (!This->pObject)
193         return E_UNEXPECTED;
194 
195     return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
196 }
197 
198 /******************************************************************************
199  *        PointerMoniker_BindToStorage
200  ******************************************************************************/
201 static HRESULT WINAPI
202 PointerMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
203                               REFIID riid, VOID** ppvResult)
204 {
205     PointerMonikerImpl *This = impl_from_IMoniker(iface);
206 
207     TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
208 
209     if (!This->pObject)
210         return E_UNEXPECTED;
211 
212     return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
213 }
214 
215 /******************************************************************************
216  *        PointerMoniker_Reduce
217  ******************************************************************************/
218 static HRESULT WINAPI
219 PointerMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
220                        IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
221 {
222     TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
223 
224     if (ppmkReduced==NULL)
225         return E_POINTER;
226 
227     PointerMonikerImpl_AddRef(iface);
228 
229     *ppmkReduced=iface;
230 
231     return MK_S_REDUCED_TO_SELF;
232 }
233 /******************************************************************************
234  *        PointerMoniker_ComposeWith
235  ******************************************************************************/
236 static HRESULT WINAPI
237 PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
238                             BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
239 {
240 
241     HRESULT res=S_OK;
242     DWORD mkSys,mkSys2;
243     IEnumMoniker* penumMk=0;
244     IMoniker *pmostLeftMk=0;
245     IMoniker* tempMkComposite=0;
246 
247     TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite);
248 
249     if ((ppmkComposite==NULL)||(pmkRight==NULL))
250 	return E_POINTER;
251 
252     *ppmkComposite=0;
253 
254     IMoniker_IsSystemMoniker(pmkRight,&mkSys);
255 
256     /* If pmkRight is an anti-moniker, the returned moniker is NULL */
257     if(mkSys==MKSYS_ANTIMONIKER)
258         return res;
259 
260     else
261         /* if pmkRight is a composite whose leftmost component is an anti-moniker,           */
262         /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
263 
264          if(mkSys==MKSYS_GENERICCOMPOSITE){
265 
266             res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
267 
268             if (FAILED(res))
269                 return res;
270 
271             res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
272 
273             IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
274 
275             if(mkSys2==MKSYS_ANTIMONIKER){
276 
277                 IMoniker_Release(pmostLeftMk);
278 
279                 tempMkComposite=iface;
280                 IMoniker_AddRef(iface);
281 
282                 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
283 
284                     res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
285 
286                     IMoniker_Release(tempMkComposite);
287                     IMoniker_Release(pmostLeftMk);
288 
289                     tempMkComposite=*ppmkComposite;
290                     IMoniker_AddRef(tempMkComposite);
291                 }
292                 return res;
293             }
294             else
295                 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
296          }
297          /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
298           composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
299           a NULL moniker and a return value of MK_E_NEEDGENERIC */
300           else
301             if (!fOnlyIfNotGeneric)
302                 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
303 
304             else
305                 return MK_E_NEEDGENERIC;
306 }
307 
308 /******************************************************************************
309  *        PointerMoniker_Enum
310  ******************************************************************************/
311 static HRESULT WINAPI
312 PointerMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
313 {
314     TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
315 
316     if (ppenumMoniker == NULL)
317         return E_POINTER;
318 
319     *ppenumMoniker = NULL;
320 
321     return S_OK;
322 }
323 
324 /******************************************************************************
325  *        PointerMoniker_IsEqual
326  ******************************************************************************/
327 static HRESULT WINAPI
328 PointerMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
329 {
330     PointerMonikerImpl *This = impl_from_IMoniker(iface);
331     DWORD mkSys;
332 
333     TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
334 
335     if (pmkOtherMoniker==NULL)
336         return S_FALSE;
337 
338     IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys);
339 
340     if (mkSys==MKSYS_POINTERMONIKER)
341     {
342         PointerMonikerImpl *pOtherMoniker = impl_from_IMoniker(pmkOtherMoniker);
343         return This->pObject == pOtherMoniker->pObject ? S_OK : S_FALSE;
344     }
345     else
346         return S_FALSE;
347 }
348 
349 /******************************************************************************
350  *        PointerMoniker_Hash
351  ******************************************************************************/
352 static HRESULT WINAPI PointerMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
353 {
354     PointerMonikerImpl *This = impl_from_IMoniker(iface);
355 
356     if (pdwHash==NULL)
357         return E_POINTER;
358 
359     *pdwHash = PtrToUlong(This->pObject);
360 
361     return S_OK;
362 }
363 
364 /******************************************************************************
365  *        PointerMoniker_IsRunning
366  ******************************************************************************/
367 static HRESULT WINAPI
368 PointerMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
369                           IMoniker* pmkNewlyRunning)
370 {
371     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
372 
373     return S_OK;
374 }
375 
376 /******************************************************************************
377  *        PointerMoniker_GetTimeOfLastChange
378  ******************************************************************************/
379 static HRESULT WINAPI PointerMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
380                                                    IBindCtx* pbc,
381                                                    IMoniker* pmkToLeft,
382                                                    FILETIME* pAntiTime)
383 {
384     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
385     return E_NOTIMPL;
386 }
387 
388 /******************************************************************************
389  *        PointerMoniker_Inverse
390  ******************************************************************************/
391 static HRESULT WINAPI
392 PointerMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
393 {
394     TRACE("(%p,%p)\n",iface,ppmk);
395 
396     return CreateAntiMoniker(ppmk);
397 }
398 
399 /******************************************************************************
400  *        PointerMoniker_CommonPrefixWith
401  ******************************************************************************/
402 static HRESULT WINAPI
403 PointerMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
404 {
405     TRACE("(%p, %p)\n", pmkOther, ppmkPrefix);
406 
407     *ppmkPrefix = NULL;
408 
409     if (PointerMonikerImpl_IsEqual(iface, pmkOther))
410     {
411         IMoniker_AddRef(iface);
412 
413         *ppmkPrefix=iface;
414 
415         return MK_S_US;
416     }
417     else
418         return MK_E_NOPREFIX;
419 }
420 
421 /******************************************************************************
422  *        PointerMoniker_RelativePathTo
423  ******************************************************************************/
424 static HRESULT WINAPI
425 PointerMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
426 {
427     TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
428 
429     if (ppmkRelPath==NULL)
430         return E_POINTER;
431 
432     *ppmkRelPath = NULL;
433 
434     return E_NOTIMPL;
435 }
436 
437 /******************************************************************************
438  *        PointerMoniker_GetDisplayName
439  ******************************************************************************/
440 static HRESULT WINAPI
441 PointerMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
442                                IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
443 {
444     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
445 
446     if (ppszDisplayName==NULL)
447         return E_POINTER;
448 
449     *ppszDisplayName = NULL;
450     return E_NOTIMPL;
451 }
452 
453 /******************************************************************************
454  *        PointerMoniker_ParseDisplayName
455  ******************************************************************************/
456 static HRESULT WINAPI
457 PointerMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
458                                  IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
459                                  ULONG* pchEaten, IMoniker** ppmkOut)
460 {
461     PointerMonikerImpl *This = impl_from_IMoniker(iface);
462     HRESULT hr;
463     IParseDisplayName *pPDN;
464 
465     TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
466 
467     if (pmkToLeft)
468         return MK_E_SYNTAX;
469 
470     if (!This->pObject)
471         return E_UNEXPECTED;
472 
473     hr = IUnknown_QueryInterface(This->pObject, &IID_IParseDisplayName, (void **)&pPDN);
474     if (FAILED(hr))
475         return hr;
476 
477     hr = IParseDisplayName_ParseDisplayName(pPDN, pbc, pszDisplayName, pchEaten, ppmkOut);
478     IParseDisplayName_Release(pPDN);
479 
480     return hr;
481 }
482 
483 /******************************************************************************
484  *        PointerMoniker_IsSystemMoniker
485  ******************************************************************************/
486 static HRESULT WINAPI
487 PointerMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
488 {
489     TRACE("(%p,%p)\n",iface,pwdMksys);
490 
491     if (!pwdMksys)
492         return E_POINTER;
493 
494     *pwdMksys = MKSYS_POINTERMONIKER;
495 
496     return S_OK;
497 }
498 
499 /********************************************************************************/
500 /* Virtual function table for the PointerMonikerImpl class which  include IPersist,*/
501 /* IPersistStream and IMoniker functions.                                       */
502 static const IMonikerVtbl VT_PointerMonikerImpl =
503 {
504     PointerMonikerImpl_QueryInterface,
505     PointerMonikerImpl_AddRef,
506     PointerMonikerImpl_Release,
507     PointerMonikerImpl_GetClassID,
508     PointerMonikerImpl_IsDirty,
509     PointerMonikerImpl_Load,
510     PointerMonikerImpl_Save,
511     PointerMonikerImpl_GetSizeMax,
512     PointerMonikerImpl_BindToObject,
513     PointerMonikerImpl_BindToStorage,
514     PointerMonikerImpl_Reduce,
515     PointerMonikerImpl_ComposeWith,
516     PointerMonikerImpl_Enum,
517     PointerMonikerImpl_IsEqual,
518     PointerMonikerImpl_Hash,
519     PointerMonikerImpl_IsRunning,
520     PointerMonikerImpl_GetTimeOfLastChange,
521     PointerMonikerImpl_Inverse,
522     PointerMonikerImpl_CommonPrefixWith,
523     PointerMonikerImpl_RelativePathTo,
524     PointerMonikerImpl_GetDisplayName,
525     PointerMonikerImpl_ParseDisplayName,
526     PointerMonikerImpl_IsSystemMoniker
527 };
528 
529 /******************************************************************************
530  *         PointerMoniker_Construct (local function)
531  *******************************************************************************/
532 static void PointerMonikerImpl_Construct(PointerMonikerImpl* This, IUnknown *punk)
533 {
534     TRACE("(%p)\n",This);
535 
536     /* Initialize the virtual function table. */
537     This->IMoniker_iface.lpVtbl = &VT_PointerMonikerImpl;
538     This->ref = 1;
539     if (punk)
540         IUnknown_AddRef(punk);
541     This->pObject      = punk;
542 }
543 
544 /***********************************************************************
545  *           CreatePointerMoniker (OLE32.@)
546  *
547  * Creates a moniker which represents a pointer.
548  *
549  * PARAMS
550  *  punk [I] Pointer to the object to represent.
551  *  ppmk [O] Address that receives the pointer to the created moniker.
552  *
553  * RETURNS
554  *  Success: S_OK.
555  *  Failure: Any HRESULT code.
556  */
557 HRESULT WINAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER *ppmk)
558 {
559     PointerMonikerImpl *This;
560 
561     TRACE("(%p, %p)\n", punk, ppmk);
562 
563     if (!ppmk)
564         return E_INVALIDARG;
565 
566     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
567     if (!This)
568     {
569         *ppmk = NULL;
570         return E_OUTOFMEMORY;
571     }
572 
573     PointerMonikerImpl_Construct(This, punk);
574     *ppmk = &This->IMoniker_iface;
575     return S_OK;
576 }
577 
578 HRESULT WINAPI PointerMoniker_CreateInstance(IClassFactory *iface,
579     IUnknown *pUnk, REFIID riid, void **ppv)
580 {
581     IMoniker *pMoniker;
582     HRESULT  hr;
583 
584     TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
585 
586     *ppv = NULL;
587 
588     if (pUnk)
589         return CLASS_E_NOAGGREGATION;
590 
591     hr = CreatePointerMoniker(NULL, &pMoniker);
592     if (FAILED(hr))
593         return hr;
594 
595     hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
596 
597     if (FAILED(hr))
598         IMoniker_Release(pMoniker);
599 
600     return hr;
601 }
602