xref: /reactos/dll/win32/ole32/antimoniker.c (revision 8a978a17)
1 /*
2  *	                      AntiMonikers implementation
3  *
4  *               Copyright 1999  Noomen Hamza
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <assert.h>
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 "objbase.h"
32 #include "wine/debug.h"
33 #include "moniker.h"
34 
35 WINE_DEFAULT_DEBUG_CHANNEL(ole);
36 
37 /* AntiMoniker data structure */
38 typedef struct AntiMonikerImpl{
39     IMoniker IMoniker_iface;
40     IROTData IROTData_iface;
41     LONG ref;
42     IUnknown *pMarshal; /* custom marshaler */
43 } AntiMonikerImpl;
44 
45 static inline AntiMonikerImpl *impl_from_IMoniker(IMoniker *iface)
46 {
47     return CONTAINING_RECORD(iface, AntiMonikerImpl, IMoniker_iface);
48 }
49 
50 static inline AntiMonikerImpl *impl_from_IROTData(IROTData *iface)
51 {
52     return CONTAINING_RECORD(iface, AntiMonikerImpl, IROTData_iface);
53 }
54 
55 
56 /*******************************************************************************
57  *        AntiMoniker_QueryInterface
58  *******************************************************************************/
59 static HRESULT WINAPI
60 AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
61 {
62     AntiMonikerImpl *This = impl_from_IMoniker(iface);
63 
64     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
65 
66     /* Perform a sanity check on the parameters.*/
67     if ( ppvObject==0 )
68 	return E_INVALIDARG;
69 
70     /* Initialize the return parameter */
71     *ppvObject = 0;
72 
73     /* Compare the riid with the interface IDs implemented by this object.*/
74     if (IsEqualIID(&IID_IUnknown, riid) ||
75         IsEqualIID(&IID_IPersist, riid) ||
76         IsEqualIID(&IID_IPersistStream, riid) ||
77         IsEqualIID(&IID_IMoniker, riid))
78         *ppvObject = iface;
79     else if (IsEqualIID(&IID_IROTData, riid))
80         *ppvObject = &This->IROTData_iface;
81     else if (IsEqualIID(&IID_IMarshal, riid))
82     {
83         HRESULT hr = S_OK;
84         if (!This->pMarshal)
85             hr = MonikerMarshal_Create(iface, &This->pMarshal);
86         if (hr != S_OK)
87             return hr;
88         return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
89     }
90 
91     /* Check that we obtained an interface.*/
92     if ((*ppvObject)==0)
93         return E_NOINTERFACE;
94 
95     /* always increase the reference count by one when it is successful */
96     IMoniker_AddRef(iface);
97 
98     return S_OK;
99 }
100 
101 /******************************************************************************
102  *        AntiMoniker_AddRef
103  ******************************************************************************/
104 static ULONG WINAPI
105 AntiMonikerImpl_AddRef(IMoniker* iface)
106 {
107     AntiMonikerImpl *This = impl_from_IMoniker(iface);
108 
109     TRACE("(%p)\n",This);
110 
111     return InterlockedIncrement(&This->ref);
112 }
113 
114 /******************************************************************************
115  *        AntiMoniker_Release
116  ******************************************************************************/
117 static ULONG WINAPI
118 AntiMonikerImpl_Release(IMoniker* iface)
119 {
120     AntiMonikerImpl *This = impl_from_IMoniker(iface);
121     ULONG ref;
122 
123     TRACE("(%p)\n",This);
124 
125     ref = InterlockedDecrement(&This->ref);
126 
127     /* destroy the object if there are no more references to it */
128     if (ref == 0)
129     {
130         if (This->pMarshal) IUnknown_Release(This->pMarshal);
131         HeapFree(GetProcessHeap(),0,This);
132     }
133 
134     return ref;
135 }
136 
137 /******************************************************************************
138  *        AntiMoniker_GetClassID
139  ******************************************************************************/
140 static HRESULT WINAPI
141 AntiMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
142 {
143     TRACE("(%p,%p)\n",iface,pClassID);
144 
145     if (pClassID==NULL)
146         return E_POINTER;
147 
148     *pClassID = CLSID_AntiMoniker;
149 
150     return S_OK;
151 }
152 
153 /******************************************************************************
154  *        AntiMoniker_IsDirty
155  ******************************************************************************/
156 static HRESULT WINAPI
157 AntiMonikerImpl_IsDirty(IMoniker* iface)
158 {
159     /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
160        method in the OLE-provided moniker interfaces always return S_FALSE because
161        their internal state never changes. */
162 
163     TRACE("(%p)\n",iface);
164 
165     return S_FALSE;
166 }
167 
168 /******************************************************************************
169  *        AntiMoniker_Load
170  ******************************************************************************/
171 static HRESULT WINAPI
172 AntiMonikerImpl_Load(IMoniker* iface,IStream* pStm)
173 {
174     DWORD constant=1,dwbuffer;
175     HRESULT res;
176 
177     /* data read by this function is only a DWORD constant (must be 1) ! */
178     res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),NULL);
179 
180     if (SUCCEEDED(res)&& dwbuffer!=constant)
181         return E_FAIL;
182 
183     return res;
184 }
185 
186 /******************************************************************************
187  *        AntiMoniker_Save
188  ******************************************************************************/
189 static HRESULT WINAPI
190 AntiMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
191 {
192     static const DWORD constant = 1;
193     /* data written by this function is only a DWORD constant set to 1 ! */
194     return IStream_Write(pStm,&constant,sizeof(constant),NULL);
195 }
196 
197 /******************************************************************************
198  *        AntiMoniker_GetSizeMax
199  *
200  * PARAMS
201  * pcbSize [out] Pointer to size of stream needed to save object
202  ******************************************************************************/
203 static HRESULT WINAPI
204 AntiMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
205 {
206     TRACE("(%p,%p)\n",iface,pcbSize);
207 
208     if (!pcbSize)
209         return E_POINTER;
210 
211     /* for more details see AntiMonikerImpl_Save comments */
212 
213     /*
214      * Normally the sizemax must be sizeof DWORD, but
215      * I tested this function it usually return 16 bytes
216      * more than the number of bytes used by AntiMoniker::Save function
217      */
218     pcbSize->u.LowPart =  sizeof(DWORD)+16;
219 
220     pcbSize->u.HighPart=0;
221 
222     return S_OK;
223 }
224 
225 /******************************************************************************
226  *                  AntiMoniker_BindToObject
227  ******************************************************************************/
228 static HRESULT WINAPI
229 AntiMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
230                              REFIID riid, VOID** ppvResult)
231 {
232     TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
233     return E_NOTIMPL;
234 }
235 
236 /******************************************************************************
237  *        AntiMoniker_BindToStorage
238  ******************************************************************************/
239 static HRESULT WINAPI
240 AntiMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
241                               REFIID riid, VOID** ppvResult)
242 {
243     TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
244     return E_NOTIMPL;
245 }
246 
247 /******************************************************************************
248  *        AntiMoniker_Reduce
249  ******************************************************************************/
250 static HRESULT WINAPI
251 AntiMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
252                        IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
253 {
254     TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
255 
256     if (ppmkReduced==NULL)
257         return E_POINTER;
258 
259     AntiMonikerImpl_AddRef(iface);
260 
261     *ppmkReduced=iface;
262 
263     return MK_S_REDUCED_TO_SELF;
264 }
265 /******************************************************************************
266  *        AntiMoniker_ComposeWith
267  ******************************************************************************/
268 static HRESULT WINAPI
269 AntiMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
270                             BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
271 {
272 
273     TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
274 
275     if ((ppmkComposite==NULL)||(pmkRight==NULL))
276 	return E_POINTER;
277 
278     *ppmkComposite=0;
279 
280     if (fOnlyIfNotGeneric)
281         return MK_E_NEEDGENERIC;
282     else
283         return CreateGenericComposite(iface,pmkRight,ppmkComposite);
284 }
285 
286 /******************************************************************************
287  *        AntiMoniker_Enum
288  ******************************************************************************/
289 static HRESULT WINAPI
290 AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
291 {
292     TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
293 
294     if (ppenumMoniker == NULL)
295         return E_POINTER;
296 
297     *ppenumMoniker = NULL;
298 
299     return S_OK;
300 }
301 
302 /******************************************************************************
303  *        AntiMoniker_IsEqual
304  ******************************************************************************/
305 static HRESULT WINAPI
306 AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
307 {
308     DWORD mkSys;
309 
310     TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
311 
312     if (pmkOtherMoniker==NULL)
313         return S_FALSE;
314 
315     IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys);
316 
317     if (mkSys==MKSYS_ANTIMONIKER)
318         return S_OK;
319     else
320         return S_FALSE;
321 }
322 
323 /******************************************************************************
324  *        AntiMoniker_Hash
325  ******************************************************************************/
326 static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
327 {
328     if (pdwHash==NULL)
329         return E_POINTER;
330 
331     *pdwHash = 0x80000001;
332 
333     return S_OK;
334 }
335 
336 /******************************************************************************
337  *        AntiMoniker_IsRunning
338  ******************************************************************************/
339 static HRESULT WINAPI
340 AntiMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
341                           IMoniker* pmkNewlyRunning)
342 {
343     IRunningObjectTable* rot;
344     HRESULT res;
345 
346     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
347 
348     if (pbc==NULL)
349         return E_INVALIDARG;
350 
351     res=IBindCtx_GetRunningObjectTable(pbc,&rot);
352 
353     if (FAILED(res))
354         return res;
355 
356     res = IRunningObjectTable_IsRunning(rot,iface);
357 
358     IRunningObjectTable_Release(rot);
359 
360     return res;
361 }
362 
363 /******************************************************************************
364  *        AntiMoniker_GetTimeOfLastChange
365  ******************************************************************************/
366 static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
367                                                    IBindCtx* pbc,
368                                                    IMoniker* pmkToLeft,
369                                                    FILETIME* pAntiTime)
370 {
371     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
372     return E_NOTIMPL;
373 }
374 
375 /******************************************************************************
376  *        AntiMoniker_Inverse
377  ******************************************************************************/
378 static HRESULT WINAPI
379 AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
380 {
381     TRACE("(%p,%p)\n",iface,ppmk);
382 
383     if (ppmk==NULL)
384         return E_POINTER;
385 
386     *ppmk=0;
387 
388     return MK_E_NOINVERSE;
389 }
390 
391 /******************************************************************************
392  *        AntiMoniker_CommonPrefixWith
393  ******************************************************************************/
394 static HRESULT WINAPI
395 AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
396 {
397     DWORD mkSys;
398 
399     IMoniker_IsSystemMoniker(pmkOther,&mkSys);
400 
401     if(mkSys==MKSYS_ANTIMONIKER){
402 
403         IMoniker_AddRef(iface);
404 
405         *ppmkPrefix=iface;
406 
407         IMoniker_AddRef(iface);
408 
409         return MK_S_US;
410     }
411     else
412         return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
413 }
414 
415 /******************************************************************************
416  *        AntiMoniker_RelativePathTo
417  ******************************************************************************/
418 static HRESULT WINAPI
419 AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
420 {
421     TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
422 
423     if (ppmkRelPath==NULL)
424         return E_POINTER;
425 
426     IMoniker_AddRef(pmOther);
427 
428     *ppmkRelPath=pmOther;
429 
430     return MK_S_HIM;
431 }
432 
433 /******************************************************************************
434  *        AntiMoniker_GetDisplayName
435  ******************************************************************************/
436 static HRESULT WINAPI
437 AntiMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
438                                IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
439 {
440     static const WCHAR back[]={'\\','.','.',0};
441 
442     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
443 
444     if (ppszDisplayName==NULL)
445         return E_POINTER;
446 
447     if (pmkToLeft!=NULL){
448         FIXME("() pmkToLeft!=NULL not implemented\n");
449         return E_NOTIMPL;
450     }
451 
452     *ppszDisplayName=CoTaskMemAlloc(sizeof(back));
453 
454     if (*ppszDisplayName==NULL)
455         return E_OUTOFMEMORY;
456 
457     lstrcpyW(*ppszDisplayName,back);
458 
459     return S_OK;
460 }
461 
462 /******************************************************************************
463  *        AntiMoniker_ParseDisplayName
464  ******************************************************************************/
465 static HRESULT WINAPI
466 AntiMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
467                                  IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
468                                  ULONG* pchEaten, IMoniker** ppmkOut)
469 {
470     TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
471     return E_NOTIMPL;
472 }
473 
474 /******************************************************************************
475  *        AntiMoniker_IsSystemMoniker
476  ******************************************************************************/
477 static HRESULT WINAPI
478 AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
479 {
480     TRACE("(%p,%p)\n",iface,pwdMksys);
481 
482     if (!pwdMksys)
483         return E_POINTER;
484 
485     (*pwdMksys)=MKSYS_ANTIMONIKER;
486 
487     return S_OK;
488 }
489 
490 /*******************************************************************************
491  *        AntiMonikerIROTData_QueryInterface
492  *******************************************************************************/
493 static HRESULT WINAPI
494 AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
495 {
496     AntiMonikerImpl *This = impl_from_IROTData(iface);
497 
498     TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject);
499 
500     return AntiMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
501 }
502 
503 /***********************************************************************
504  *        AntiMonikerIROTData_AddRef
505  */
506 static ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface)
507 {
508     AntiMonikerImpl *This = impl_from_IROTData(iface);
509 
510     TRACE("(%p)\n",iface);
511 
512     return AntiMonikerImpl_AddRef(&This->IMoniker_iface);
513 }
514 
515 /***********************************************************************
516  *        AntiMonikerIROTData_Release
517  */
518 static ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface)
519 {
520     AntiMonikerImpl *This = impl_from_IROTData(iface);
521 
522     TRACE("(%p)\n",iface);
523 
524     return AntiMonikerImpl_Release(&This->IMoniker_iface);
525 }
526 
527 /******************************************************************************
528  *        AntiMonikerIROTData_GetComparisonData
529  ******************************************************************************/
530 static HRESULT WINAPI
531 AntiMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData,
532                                           ULONG cbMax, ULONG* pcbData)
533 {
534     DWORD constant = 1;
535 
536     TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
537 
538     *pcbData = sizeof(CLSID) + sizeof(DWORD);
539     if (cbMax < *pcbData)
540         return E_OUTOFMEMORY;
541 
542     memcpy(pbData, &CLSID_AntiMoniker, sizeof(CLSID));
543     memcpy(pbData+sizeof(CLSID), &constant, sizeof(DWORD));
544 
545     return S_OK;
546 }
547 
548 /********************************************************************************/
549 /* Virtual function table for the AntiMonikerImpl class which  include IPersist,*/
550 /* IPersistStream and IMoniker functions.                                       */
551 static const IMonikerVtbl VT_AntiMonikerImpl =
552 {
553     AntiMonikerImpl_QueryInterface,
554     AntiMonikerImpl_AddRef,
555     AntiMonikerImpl_Release,
556     AntiMonikerImpl_GetClassID,
557     AntiMonikerImpl_IsDirty,
558     AntiMonikerImpl_Load,
559     AntiMonikerImpl_Save,
560     AntiMonikerImpl_GetSizeMax,
561     AntiMonikerImpl_BindToObject,
562     AntiMonikerImpl_BindToStorage,
563     AntiMonikerImpl_Reduce,
564     AntiMonikerImpl_ComposeWith,
565     AntiMonikerImpl_Enum,
566     AntiMonikerImpl_IsEqual,
567     AntiMonikerImpl_Hash,
568     AntiMonikerImpl_IsRunning,
569     AntiMonikerImpl_GetTimeOfLastChange,
570     AntiMonikerImpl_Inverse,
571     AntiMonikerImpl_CommonPrefixWith,
572     AntiMonikerImpl_RelativePathTo,
573     AntiMonikerImpl_GetDisplayName,
574     AntiMonikerImpl_ParseDisplayName,
575     AntiMonikerImpl_IsSystemMoniker
576 };
577 
578 /********************************************************************************/
579 /* Virtual function table for the IROTData class.                               */
580 static const IROTDataVtbl VT_ROTDataImpl =
581 {
582     AntiMonikerROTDataImpl_QueryInterface,
583     AntiMonikerROTDataImpl_AddRef,
584     AntiMonikerROTDataImpl_Release,
585     AntiMonikerROTDataImpl_GetComparisonData
586 };
587 
588 /******************************************************************************
589  *         AntiMoniker_Construct (local function)
590  *******************************************************************************/
591 static HRESULT AntiMonikerImpl_Construct(AntiMonikerImpl* This)
592 {
593 
594     TRACE("(%p)\n",This);
595 
596     /* Initialize the virtual function table. */
597     This->IMoniker_iface.lpVtbl = &VT_AntiMonikerImpl;
598     This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
599     This->ref          = 0;
600     This->pMarshal     = NULL;
601 
602     return S_OK;
603 }
604 
605 /******************************************************************************
606  *        CreateAntiMoniker	[OLE32.@]
607  ******************************************************************************/
608 HRESULT WINAPI CreateAntiMoniker(IMoniker **ppmk)
609 {
610     AntiMonikerImpl* newAntiMoniker;
611     HRESULT hr;
612 
613     TRACE("(%p)\n",ppmk);
614 
615     newAntiMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(AntiMonikerImpl));
616 
617     if (newAntiMoniker == 0)
618         return STG_E_INSUFFICIENTMEMORY;
619 
620     hr = AntiMonikerImpl_Construct(newAntiMoniker);
621     if (FAILED(hr))
622     {
623         HeapFree(GetProcessHeap(),0,newAntiMoniker);
624         return hr;
625     }
626 
627     return AntiMonikerImpl_QueryInterface(&newAntiMoniker->IMoniker_iface, &IID_IMoniker,
628             (void**)ppmk);
629 }
630 
631 HRESULT WINAPI AntiMoniker_CreateInstance(IClassFactory *iface,
632     IUnknown *pUnk, REFIID riid, void **ppv)
633 {
634     IMoniker *pMoniker;
635     HRESULT  hr;
636 
637     TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
638 
639     *ppv = NULL;
640 
641     if (pUnk)
642         return CLASS_E_NOAGGREGATION;
643 
644     hr = CreateAntiMoniker(&pMoniker);
645     if (FAILED(hr))
646         return hr;
647 
648     hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
649 
650     if (FAILED(hr))
651         IMoniker_Release(pMoniker);
652 
653     return hr;
654 }
655