widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / ole32 / antimoniker.c
blobc0937a8d903a9446819725e440aebd6c71bf5dd4
1 /*
2 * AntiMonikers implementation
4 * Copyright 1999 Noomen Hamza
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.
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.
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
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <string.h>
25 #define COBJMACROS
26 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "objbase.h"
32 #include "wine/debug.h"
33 #include "wine/heap.h"
34 #include "moniker.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole);
38 /* AntiMoniker data structure */
39 typedef struct AntiMonikerImpl{
40 IMoniker IMoniker_iface;
41 IROTData IROTData_iface;
42 LONG refcount;
43 IUnknown *pMarshal; /* custom marshaler */
44 DWORD count;
45 } AntiMonikerImpl;
47 static inline AntiMonikerImpl *impl_from_IMoniker(IMoniker *iface)
49 return CONTAINING_RECORD(iface, AntiMonikerImpl, IMoniker_iface);
52 static inline AntiMonikerImpl *impl_from_IROTData(IROTData *iface)
54 return CONTAINING_RECORD(iface, AntiMonikerImpl, IROTData_iface);
57 static AntiMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface);
59 BOOL is_anti_moniker(IMoniker *iface, DWORD *order)
61 AntiMonikerImpl *moniker = unsafe_impl_from_IMoniker(iface);
63 if (!moniker)
65 *order = 0;
66 return FALSE;
69 *order = moniker->count;
71 return TRUE;
74 /*******************************************************************************
75 * AntiMoniker_QueryInterface
76 *******************************************************************************/
77 static HRESULT WINAPI
78 AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
80 AntiMonikerImpl *This = impl_from_IMoniker(iface);
82 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
84 if ( ppvObject==0 )
85 return E_INVALIDARG;
87 *ppvObject = 0;
89 if (IsEqualIID(&IID_IUnknown, riid) ||
90 IsEqualIID(&IID_IPersist, riid) ||
91 IsEqualIID(&IID_IPersistStream, riid) ||
92 IsEqualIID(&IID_IMoniker, riid) ||
93 IsEqualGUID(&CLSID_AntiMoniker, riid))
95 *ppvObject = iface;
97 else if (IsEqualIID(&IID_IROTData, riid))
98 *ppvObject = &This->IROTData_iface;
99 else if (IsEqualIID(&IID_IMarshal, riid))
101 HRESULT hr = S_OK;
102 if (!This->pMarshal)
103 hr = MonikerMarshal_Create(iface, &This->pMarshal);
104 if (hr != S_OK)
105 return hr;
106 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
109 if ((*ppvObject)==0)
110 return E_NOINTERFACE;
112 IMoniker_AddRef(iface);
114 return S_OK;
117 /******************************************************************************
118 * AntiMoniker_AddRef
119 ******************************************************************************/
120 static ULONG WINAPI AntiMonikerImpl_AddRef(IMoniker *iface)
122 AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
123 ULONG refcount = InterlockedIncrement(&moniker->refcount);
125 TRACE("%p, refcount %u.\n", iface, refcount);
127 return refcount;
130 /******************************************************************************
131 * AntiMoniker_Release
132 ******************************************************************************/
133 static ULONG WINAPI AntiMonikerImpl_Release(IMoniker *iface)
135 AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
136 ULONG refcount = InterlockedDecrement(&moniker->refcount);
138 TRACE("%p, refcount %u.\n", iface, refcount);
140 if (!refcount)
142 if (moniker->pMarshal) IUnknown_Release(moniker->pMarshal);
143 heap_free(moniker);
146 return refcount;
149 /******************************************************************************
150 * AntiMoniker_GetClassID
151 ******************************************************************************/
152 static HRESULT WINAPI
153 AntiMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
155 TRACE("(%p,%p)\n",iface,pClassID);
157 if (pClassID==NULL)
158 return E_POINTER;
160 *pClassID = CLSID_AntiMoniker;
162 return S_OK;
165 /******************************************************************************
166 * AntiMoniker_IsDirty
167 ******************************************************************************/
168 static HRESULT WINAPI
169 AntiMonikerImpl_IsDirty(IMoniker* iface)
171 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
172 method in the OLE-provided moniker interfaces always return S_FALSE because
173 their internal state never changes. */
175 TRACE("(%p)\n",iface);
177 return S_FALSE;
180 /******************************************************************************
181 * AntiMoniker_Load
182 ******************************************************************************/
183 static HRESULT WINAPI AntiMonikerImpl_Load(IMoniker *iface, IStream *stream)
185 AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
186 DWORD count = 0;
187 HRESULT hr;
189 TRACE("%p, %p.\n", iface, stream);
191 if (FAILED(hr = IStream_Read(stream, &count, sizeof(count), NULL)))
192 return hr;
194 if (count > 0xfffff)
195 return E_INVALIDARG;
197 moniker->count = count;
199 return S_OK;
202 /******************************************************************************
203 * AntiMoniker_Save
204 ******************************************************************************/
205 static HRESULT WINAPI AntiMonikerImpl_Save(IMoniker *iface, IStream *stream, BOOL clear_dirty)
207 AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
209 TRACE("%p, %p, %d.\n", iface, stream, clear_dirty);
211 return IStream_Write(stream, &moniker->count, sizeof(moniker->count), NULL);
214 /******************************************************************************
215 * AntiMoniker_GetSizeMax
217 * PARAMS
218 * pcbSize [out] Pointer to size of stream needed to save object
219 ******************************************************************************/
220 static HRESULT WINAPI
221 AntiMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
223 TRACE("(%p,%p)\n",iface,pcbSize);
225 if (!pcbSize)
226 return E_POINTER;
228 /* for more details see AntiMonikerImpl_Save comments */
231 * Normally the sizemax must be sizeof DWORD, but
232 * I tested this function it usually return 16 bytes
233 * more than the number of bytes used by AntiMoniker::Save function
235 pcbSize->u.LowPart = sizeof(DWORD)+16;
237 pcbSize->u.HighPart=0;
239 return S_OK;
242 /******************************************************************************
243 * AntiMoniker_BindToObject
244 ******************************************************************************/
245 static HRESULT WINAPI
246 AntiMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
247 REFIID riid, VOID** ppvResult)
249 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
250 return E_NOTIMPL;
253 /******************************************************************************
254 * AntiMoniker_BindToStorage
255 ******************************************************************************/
256 static HRESULT WINAPI
257 AntiMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
258 REFIID riid, VOID** ppvResult)
260 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
261 return E_NOTIMPL;
264 /******************************************************************************
265 * AntiMoniker_Reduce
266 ******************************************************************************/
267 static HRESULT WINAPI
268 AntiMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
269 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
271 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
273 if (ppmkReduced==NULL)
274 return E_POINTER;
276 AntiMonikerImpl_AddRef(iface);
278 *ppmkReduced=iface;
280 return MK_S_REDUCED_TO_SELF;
282 /******************************************************************************
283 * AntiMoniker_ComposeWith
284 ******************************************************************************/
285 static HRESULT WINAPI
286 AntiMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
287 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
290 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
292 if ((ppmkComposite==NULL)||(pmkRight==NULL))
293 return E_POINTER;
295 *ppmkComposite=0;
297 if (fOnlyIfNotGeneric)
298 return MK_E_NEEDGENERIC;
299 else
300 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
303 /******************************************************************************
304 * AntiMoniker_Enum
305 ******************************************************************************/
306 static HRESULT WINAPI
307 AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
309 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
311 if (ppenumMoniker == NULL)
312 return E_POINTER;
314 *ppenumMoniker = NULL;
316 return S_OK;
319 /******************************************************************************
320 * AntiMoniker_IsEqual
321 ******************************************************************************/
322 static HRESULT WINAPI AntiMonikerImpl_IsEqual(IMoniker *iface, IMoniker *other)
324 AntiMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
326 TRACE("%p, %p.\n", iface, other);
328 if (!other)
329 return E_INVALIDARG;
331 other_moniker = unsafe_impl_from_IMoniker(other);
332 if (!other_moniker)
333 return S_FALSE;
335 return moniker->count == other_moniker->count ? S_OK : S_FALSE;
338 /******************************************************************************
339 * AntiMoniker_Hash
340 ******************************************************************************/
341 static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker *iface, DWORD *hash)
343 AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
345 TRACE("%p, %p.\n", iface, hash);
347 if (!hash)
348 return E_POINTER;
350 *hash = 0x80000000 | moniker->count;
352 return S_OK;
355 /******************************************************************************
356 * AntiMoniker_IsRunning
357 ******************************************************************************/
358 static HRESULT WINAPI
359 AntiMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
360 IMoniker* pmkNewlyRunning)
362 IRunningObjectTable* rot;
363 HRESULT res;
365 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
367 if (pbc==NULL)
368 return E_INVALIDARG;
370 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
372 if (FAILED(res))
373 return res;
375 res = IRunningObjectTable_IsRunning(rot,iface);
377 IRunningObjectTable_Release(rot);
379 return res;
382 /******************************************************************************
383 * AntiMoniker_GetTimeOfLastChange
384 ******************************************************************************/
385 static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
386 IBindCtx* pbc,
387 IMoniker* pmkToLeft,
388 FILETIME* pAntiTime)
390 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
391 return E_NOTIMPL;
394 /******************************************************************************
395 * AntiMoniker_Inverse
396 ******************************************************************************/
397 static HRESULT WINAPI
398 AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
400 TRACE("(%p,%p)\n",iface,ppmk);
402 if (ppmk==NULL)
403 return E_POINTER;
405 *ppmk=0;
407 return MK_E_NOINVERSE;
410 /******************************************************************************
411 * AntiMoniker_CommonPrefixWith
412 ******************************************************************************/
413 static HRESULT WINAPI AntiMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other, IMoniker **prefix)
415 AntiMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
416 HRESULT hr;
418 TRACE("%p, %p, %p.\n", iface, other, prefix);
420 other_moniker = unsafe_impl_from_IMoniker(other);
421 if (other_moniker)
423 if (moniker->count <= other_moniker->count)
425 *prefix = iface;
426 hr = moniker->count == other_moniker->count ? MK_S_US : MK_S_ME;
428 else
430 *prefix = other;
431 hr = MK_S_HIM;
434 IMoniker_AddRef(*prefix);
435 return hr;
438 return MonikerCommonPrefixWith(iface, other, prefix);
441 /******************************************************************************
442 * AntiMoniker_RelativePathTo
443 ******************************************************************************/
444 static HRESULT WINAPI
445 AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
447 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
449 if (ppmkRelPath==NULL)
450 return E_POINTER;
452 IMoniker_AddRef(pmOther);
454 *ppmkRelPath=pmOther;
456 return MK_S_HIM;
459 /******************************************************************************
460 * AntiMoniker_GetDisplayName
461 ******************************************************************************/
462 static HRESULT WINAPI
463 AntiMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *displayname)
465 AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
466 static const WCHAR nameW[] = {'\\','.','.'};
467 WCHAR *ptrW;
468 int i;
470 TRACE("%p, %p, %p, %p.\n", iface, pbc, pmkToLeft, displayname);
472 if (!displayname)
473 return E_POINTER;
475 if (pmkToLeft!=NULL){
476 FIXME("() pmkToLeft!=NULL not implemented\n");
477 return E_NOTIMPL;
480 *displayname = ptrW = CoTaskMemAlloc((moniker->count * ARRAY_SIZE(nameW) + 1) * sizeof(WCHAR));
481 if (!*displayname)
482 return E_OUTOFMEMORY;
484 for (i = 0; i < moniker->count; ++i)
485 memcpy(ptrW + i * ARRAY_SIZE(nameW), nameW, sizeof(nameW));
486 ptrW[moniker->count * ARRAY_SIZE(nameW)] = 0;
488 return S_OK;
491 /******************************************************************************
492 * AntiMoniker_ParseDisplayName
493 ******************************************************************************/
494 static HRESULT WINAPI
495 AntiMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
496 IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
497 ULONG* pchEaten, IMoniker** ppmkOut)
499 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
500 return E_NOTIMPL;
503 /******************************************************************************
504 * AntiMoniker_IsSystemMoniker
505 ******************************************************************************/
506 static HRESULT WINAPI
507 AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
509 TRACE("(%p,%p)\n",iface,pwdMksys);
511 if (!pwdMksys)
512 return E_POINTER;
514 (*pwdMksys)=MKSYS_ANTIMONIKER;
516 return S_OK;
519 /*******************************************************************************
520 * AntiMonikerIROTData_QueryInterface
521 *******************************************************************************/
522 static HRESULT WINAPI
523 AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
525 AntiMonikerImpl *This = impl_from_IROTData(iface);
527 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject);
529 return AntiMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
532 /***********************************************************************
533 * AntiMonikerIROTData_AddRef
535 static ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface)
537 AntiMonikerImpl *This = impl_from_IROTData(iface);
539 TRACE("(%p)\n",iface);
541 return AntiMonikerImpl_AddRef(&This->IMoniker_iface);
544 /***********************************************************************
545 * AntiMonikerIROTData_Release
547 static ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface)
549 AntiMonikerImpl *This = impl_from_IROTData(iface);
551 TRACE("(%p)\n",iface);
553 return AntiMonikerImpl_Release(&This->IMoniker_iface);
556 /******************************************************************************
557 * AntiMonikerIROTData_GetComparisonData
558 ******************************************************************************/
559 static HRESULT WINAPI
560 AntiMonikerROTDataImpl_GetComparisonData(IROTData *iface, BYTE *data, ULONG data_len, ULONG *data_req)
562 AntiMonikerImpl *moniker = impl_from_IROTData(iface);
564 TRACE("%p, %p, %u, %p.\n", iface, data, data_len, data_req);
566 *data_req = sizeof(CLSID) + sizeof(DWORD);
567 if (data_len < *data_req)
568 return E_OUTOFMEMORY;
570 memcpy(data, &CLSID_AntiMoniker, sizeof(CLSID));
571 memcpy(data + sizeof(CLSID), &moniker->count, sizeof(moniker->count));
573 return S_OK;
576 /********************************************************************************/
577 /* Virtual function table for the AntiMonikerImpl class which include IPersist,*/
578 /* IPersistStream and IMoniker functions. */
579 static const IMonikerVtbl VT_AntiMonikerImpl =
581 AntiMonikerImpl_QueryInterface,
582 AntiMonikerImpl_AddRef,
583 AntiMonikerImpl_Release,
584 AntiMonikerImpl_GetClassID,
585 AntiMonikerImpl_IsDirty,
586 AntiMonikerImpl_Load,
587 AntiMonikerImpl_Save,
588 AntiMonikerImpl_GetSizeMax,
589 AntiMonikerImpl_BindToObject,
590 AntiMonikerImpl_BindToStorage,
591 AntiMonikerImpl_Reduce,
592 AntiMonikerImpl_ComposeWith,
593 AntiMonikerImpl_Enum,
594 AntiMonikerImpl_IsEqual,
595 AntiMonikerImpl_Hash,
596 AntiMonikerImpl_IsRunning,
597 AntiMonikerImpl_GetTimeOfLastChange,
598 AntiMonikerImpl_Inverse,
599 AntiMonikerImpl_CommonPrefixWith,
600 AntiMonikerImpl_RelativePathTo,
601 AntiMonikerImpl_GetDisplayName,
602 AntiMonikerImpl_ParseDisplayName,
603 AntiMonikerImpl_IsSystemMoniker
606 static AntiMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface)
608 if (iface->lpVtbl != &VT_AntiMonikerImpl)
609 return NULL;
610 return CONTAINING_RECORD(iface, AntiMonikerImpl, IMoniker_iface);
613 /********************************************************************************/
614 /* Virtual function table for the IROTData class. */
615 static const IROTDataVtbl VT_ROTDataImpl =
617 AntiMonikerROTDataImpl_QueryInterface,
618 AntiMonikerROTDataImpl_AddRef,
619 AntiMonikerROTDataImpl_Release,
620 AntiMonikerROTDataImpl_GetComparisonData
623 HRESULT create_anti_moniker(DWORD order, IMoniker **ret)
625 AntiMonikerImpl *moniker;
627 moniker = heap_alloc_zero(sizeof(*moniker));
628 if (!moniker)
629 return E_OUTOFMEMORY;
631 moniker->IMoniker_iface.lpVtbl = &VT_AntiMonikerImpl;
632 moniker->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
633 moniker->refcount = 1;
634 moniker->count = order;
636 *ret = &moniker->IMoniker_iface;
638 return S_OK;
641 /******************************************************************************
642 * CreateAntiMoniker [OLE32.@]
643 ******************************************************************************/
644 HRESULT WINAPI CreateAntiMoniker(IMoniker **moniker)
646 TRACE("%p.\n", moniker);
648 return create_anti_moniker(1, moniker);
651 HRESULT WINAPI AntiMoniker_CreateInstance(IClassFactory *iface,
652 IUnknown *pUnk, REFIID riid, void **ppv)
654 IMoniker *pMoniker;
655 HRESULT hr;
657 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
659 *ppv = NULL;
661 if (pUnk)
662 return CLASS_E_NOAGGREGATION;
664 hr = CreateAntiMoniker(&pMoniker);
665 if (FAILED(hr))
666 return hr;
668 hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
669 IMoniker_Release(pMoniker);
671 return hr;