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