ddraw/tests: Move the capability tests for enumerated devices.
[wine.git] / dlls / ole32 / antimoniker.c
blob2a7be8e75cc5f667411a10c92a2fec4e946c6355
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 %lu.\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 %lu.\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 static HRESULT WINAPI
265 AntiMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
266 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
268 TRACE("%p, %p, %ld, %p, %p.\n", iface, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
270 if (ppmkReduced==NULL)
271 return E_POINTER;
273 AntiMonikerImpl_AddRef(iface);
275 *ppmkReduced=iface;
277 return MK_S_REDUCED_TO_SELF;
279 /******************************************************************************
280 * AntiMoniker_ComposeWith
281 ******************************************************************************/
282 static HRESULT WINAPI
283 AntiMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
284 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
287 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
289 if ((ppmkComposite==NULL)||(pmkRight==NULL))
290 return E_POINTER;
292 *ppmkComposite=0;
294 if (fOnlyIfNotGeneric)
295 return MK_E_NEEDGENERIC;
296 else
297 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
300 /******************************************************************************
301 * AntiMoniker_Enum
302 ******************************************************************************/
303 static HRESULT WINAPI
304 AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
306 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
308 if (ppenumMoniker == NULL)
309 return E_POINTER;
311 *ppenumMoniker = NULL;
313 return S_OK;
316 /******************************************************************************
317 * AntiMoniker_IsEqual
318 ******************************************************************************/
319 static HRESULT WINAPI AntiMonikerImpl_IsEqual(IMoniker *iface, IMoniker *other)
321 AntiMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
323 TRACE("%p, %p.\n", iface, other);
325 if (!other)
326 return E_INVALIDARG;
328 other_moniker = unsafe_impl_from_IMoniker(other);
329 if (!other_moniker)
330 return S_FALSE;
332 return moniker->count == other_moniker->count ? S_OK : S_FALSE;
335 /******************************************************************************
336 * AntiMoniker_Hash
337 ******************************************************************************/
338 static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker *iface, DWORD *hash)
340 AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
342 TRACE("%p, %p.\n", iface, hash);
344 if (!hash)
345 return E_POINTER;
347 *hash = 0x80000000 | moniker->count;
349 return S_OK;
352 /******************************************************************************
353 * AntiMoniker_IsRunning
354 ******************************************************************************/
355 static HRESULT WINAPI
356 AntiMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
357 IMoniker* pmkNewlyRunning)
359 IRunningObjectTable* rot;
360 HRESULT res;
362 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
364 if (pbc==NULL)
365 return E_INVALIDARG;
367 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
369 if (FAILED(res))
370 return res;
372 res = IRunningObjectTable_IsRunning(rot,iface);
374 IRunningObjectTable_Release(rot);
376 return res;
379 /******************************************************************************
380 * AntiMoniker_GetTimeOfLastChange
381 ******************************************************************************/
382 static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
383 IBindCtx* pbc,
384 IMoniker* pmkToLeft,
385 FILETIME* pAntiTime)
387 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
388 return E_NOTIMPL;
391 /******************************************************************************
392 * AntiMoniker_Inverse
393 ******************************************************************************/
394 static HRESULT WINAPI
395 AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
397 TRACE("(%p,%p)\n",iface,ppmk);
399 if (ppmk==NULL)
400 return E_POINTER;
402 *ppmk=0;
404 return MK_E_NOINVERSE;
407 /******************************************************************************
408 * AntiMoniker_CommonPrefixWith
409 ******************************************************************************/
410 static HRESULT WINAPI AntiMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other, IMoniker **prefix)
412 AntiMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
413 HRESULT hr;
415 TRACE("%p, %p, %p.\n", iface, other, prefix);
417 other_moniker = unsafe_impl_from_IMoniker(other);
418 if (other_moniker)
420 if (moniker->count <= other_moniker->count)
422 *prefix = iface;
423 hr = moniker->count == other_moniker->count ? MK_S_US : MK_S_ME;
425 else
427 *prefix = other;
428 hr = MK_S_HIM;
431 IMoniker_AddRef(*prefix);
432 return hr;
435 return MonikerCommonPrefixWith(iface, other, prefix);
438 static HRESULT WINAPI AntiMonikerImpl_RelativePathTo(IMoniker *iface, IMoniker *other, IMoniker **result)
440 TRACE("%p, %p, %p.\n", iface, other, result);
442 if (!other || !result)
443 return E_INVALIDARG;
445 IMoniker_AddRef(other);
446 *result = other;
448 return MK_S_HIM;
451 /******************************************************************************
452 * AntiMoniker_GetDisplayName
453 ******************************************************************************/
454 static HRESULT WINAPI
455 AntiMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *displayname)
457 AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
458 static const WCHAR nameW[] = {'\\','.','.'};
459 WCHAR *ptrW;
460 int i;
462 TRACE("%p, %p, %p, %p.\n", iface, pbc, pmkToLeft, displayname);
464 if (!displayname)
465 return E_POINTER;
467 if (pmkToLeft!=NULL){
468 FIXME("() pmkToLeft!=NULL not implemented\n");
469 return E_NOTIMPL;
472 *displayname = ptrW = CoTaskMemAlloc((moniker->count * ARRAY_SIZE(nameW) + 1) * sizeof(WCHAR));
473 if (!*displayname)
474 return E_OUTOFMEMORY;
476 for (i = 0; i < moniker->count; ++i)
477 memcpy(ptrW + i * ARRAY_SIZE(nameW), nameW, sizeof(nameW));
478 ptrW[moniker->count * ARRAY_SIZE(nameW)] = 0;
480 return S_OK;
483 /******************************************************************************
484 * AntiMoniker_ParseDisplayName
485 ******************************************************************************/
486 static HRESULT WINAPI
487 AntiMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
488 IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
489 ULONG* pchEaten, IMoniker** ppmkOut)
491 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
492 return E_NOTIMPL;
495 /******************************************************************************
496 * AntiMoniker_IsSystemMoniker
497 ******************************************************************************/
498 static HRESULT WINAPI
499 AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
501 TRACE("(%p,%p)\n",iface,pwdMksys);
503 if (!pwdMksys)
504 return E_POINTER;
506 (*pwdMksys)=MKSYS_ANTIMONIKER;
508 return S_OK;
511 /*******************************************************************************
512 * AntiMonikerIROTData_QueryInterface
513 *******************************************************************************/
514 static HRESULT WINAPI
515 AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
517 AntiMonikerImpl *This = impl_from_IROTData(iface);
519 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject);
521 return AntiMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
524 /***********************************************************************
525 * AntiMonikerIROTData_AddRef
527 static ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface)
529 AntiMonikerImpl *This = impl_from_IROTData(iface);
531 TRACE("(%p)\n",iface);
533 return AntiMonikerImpl_AddRef(&This->IMoniker_iface);
536 /***********************************************************************
537 * AntiMonikerIROTData_Release
539 static ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface)
541 AntiMonikerImpl *This = impl_from_IROTData(iface);
543 TRACE("(%p)\n",iface);
545 return AntiMonikerImpl_Release(&This->IMoniker_iface);
548 /******************************************************************************
549 * AntiMonikerIROTData_GetComparisonData
550 ******************************************************************************/
551 static HRESULT WINAPI
552 AntiMonikerROTDataImpl_GetComparisonData(IROTData *iface, BYTE *data, ULONG data_len, ULONG *data_req)
554 AntiMonikerImpl *moniker = impl_from_IROTData(iface);
556 TRACE("%p, %p, %lu, %p.\n", iface, data, data_len, data_req);
558 *data_req = sizeof(CLSID) + sizeof(DWORD);
559 if (data_len < *data_req)
560 return E_OUTOFMEMORY;
562 memcpy(data, &CLSID_AntiMoniker, sizeof(CLSID));
563 memcpy(data + sizeof(CLSID), &moniker->count, sizeof(moniker->count));
565 return S_OK;
568 /********************************************************************************/
569 /* Virtual function table for the AntiMonikerImpl class which include IPersist,*/
570 /* IPersistStream and IMoniker functions. */
571 static const IMonikerVtbl VT_AntiMonikerImpl =
573 AntiMonikerImpl_QueryInterface,
574 AntiMonikerImpl_AddRef,
575 AntiMonikerImpl_Release,
576 AntiMonikerImpl_GetClassID,
577 AntiMonikerImpl_IsDirty,
578 AntiMonikerImpl_Load,
579 AntiMonikerImpl_Save,
580 AntiMonikerImpl_GetSizeMax,
581 AntiMonikerImpl_BindToObject,
582 AntiMonikerImpl_BindToStorage,
583 AntiMonikerImpl_Reduce,
584 AntiMonikerImpl_ComposeWith,
585 AntiMonikerImpl_Enum,
586 AntiMonikerImpl_IsEqual,
587 AntiMonikerImpl_Hash,
588 AntiMonikerImpl_IsRunning,
589 AntiMonikerImpl_GetTimeOfLastChange,
590 AntiMonikerImpl_Inverse,
591 AntiMonikerImpl_CommonPrefixWith,
592 AntiMonikerImpl_RelativePathTo,
593 AntiMonikerImpl_GetDisplayName,
594 AntiMonikerImpl_ParseDisplayName,
595 AntiMonikerImpl_IsSystemMoniker
598 static AntiMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface)
600 if (iface->lpVtbl != &VT_AntiMonikerImpl)
601 return NULL;
602 return CONTAINING_RECORD(iface, AntiMonikerImpl, IMoniker_iface);
605 /********************************************************************************/
606 /* Virtual function table for the IROTData class. */
607 static const IROTDataVtbl VT_ROTDataImpl =
609 AntiMonikerROTDataImpl_QueryInterface,
610 AntiMonikerROTDataImpl_AddRef,
611 AntiMonikerROTDataImpl_Release,
612 AntiMonikerROTDataImpl_GetComparisonData
615 HRESULT create_anti_moniker(DWORD order, IMoniker **ret)
617 AntiMonikerImpl *moniker;
619 moniker = heap_alloc_zero(sizeof(*moniker));
620 if (!moniker)
621 return E_OUTOFMEMORY;
623 moniker->IMoniker_iface.lpVtbl = &VT_AntiMonikerImpl;
624 moniker->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
625 moniker->refcount = 1;
626 moniker->count = order;
628 *ret = &moniker->IMoniker_iface;
630 return S_OK;
633 /******************************************************************************
634 * CreateAntiMoniker [OLE32.@]
635 ******************************************************************************/
636 HRESULT WINAPI CreateAntiMoniker(IMoniker **moniker)
638 TRACE("%p.\n", moniker);
640 return create_anti_moniker(1, moniker);
643 HRESULT WINAPI AntiMoniker_CreateInstance(IClassFactory *iface,
644 IUnknown *pUnk, REFIID riid, void **ppv)
646 IMoniker *pMoniker;
647 HRESULT hr;
649 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
651 *ppv = NULL;
653 if (pUnk)
654 return CLASS_E_NOAGGREGATION;
656 hr = CreateAntiMoniker(&pMoniker);
657 if (FAILED(hr))
658 return hr;
660 hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
661 IMoniker_Release(pMoniker);
663 return hr;