When including 'wine/port.h', include it first.
[wine] / dlls / quartz / iunk.c
1 /*
2  * An implementation of IUnknown.
3  *
4  * hidenori@a2.ctktv.ne.jp
5  */
6
7 #include "config.h"
8
9 #include "windef.h"
10 #include "winerror.h"
11 #include "winbase.h"
12 #include "wine/obj_base.h"
13
14 #include "debugtools.h"
15 DEFAULT_DEBUG_CHANNEL(quartz);
16
17 #include "quartz_private.h"
18 #include "iunk.h"
19
20
21 static HRESULT WINAPI
22 IUnknown_fnQueryInterface(IUnknown* iface,REFIID riid,LPVOID *ppobj)
23 {
24         ICOM_THIS(QUARTZ_IUnkImpl,iface);
25         size_t  ofs;
26         DWORD   dwIndex;
27         QUARTZ_IFDelegation*    pDelegation;
28         HRESULT hr;
29
30         TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
31
32         if ( ppobj == NULL )
33                 return E_POINTER;
34         *ppobj = NULL;
35
36         ofs = 0;
37
38         if ( IsEqualGUID( &IID_IUnknown, riid ) )
39         {
40                 TRACE("IID_IUnknown - returns inner object.\n");
41         }
42         else
43         {
44                 for ( dwIndex = 0; dwIndex < This->dwEntries; dwIndex++ )
45                 {
46                         if ( IsEqualGUID( This->pEntries[dwIndex].piid, riid ) )
47                         {
48                                 ofs = This->pEntries[dwIndex].ofsVTPtr;
49                                 break;
50                         }
51                 }
52                 if ( dwIndex == This->dwEntries )
53                 {
54                         hr = E_NOINTERFACE;
55
56                         /* delegation */
57                         pDelegation = This->pDelegationFirst;
58                         while ( pDelegation != NULL )
59                         {
60                                 hr = (*pDelegation->pOnQueryInterface)( iface, riid, ppobj );
61                                 if ( hr != E_NOINTERFACE )
62                                         break;
63                                 pDelegation = pDelegation->pNext;
64                         }
65
66                         if ( hr == E_NOINTERFACE )
67                         {
68                                 FIXME("(%p) unknown interface: %s\n",This,debugstr_guid(riid));
69                         }
70
71                         return hr;
72                 }
73         }
74
75         *ppobj = (LPVOID)(((char*)This) + ofs);
76         IUnknown_AddRef((IUnknown*)(*ppobj));
77
78         return S_OK;
79 }
80
81 static ULONG WINAPI
82 IUnknown_fnAddRef(IUnknown* iface)
83 {
84         ICOM_THIS(QUARTZ_IUnkImpl,iface);
85
86         TRACE("(%p)->()\n",This);
87
88         return InterlockedExchangeAdd(&(This->ref),1) + 1;
89 }
90
91 static ULONG WINAPI
92 IUnknown_fnRelease(IUnknown* iface)
93 {
94         ICOM_THIS(QUARTZ_IUnkImpl,iface);
95         LONG    ref;
96
97         TRACE("(%p)->()\n",This);
98         ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
99         if ( ref > 0 )
100                 return (ULONG)ref;
101
102         if ( This->pOnFinalRelease != NULL )
103                 (*(This->pOnFinalRelease))(iface);
104
105         QUARTZ_FreeObj(This);
106
107         return 0;
108 }
109
110 static ICOM_VTABLE(IUnknown) iunknown =
111 {
112         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
113         /* IUnknown fields */
114         IUnknown_fnQueryInterface,
115         IUnknown_fnAddRef,
116         IUnknown_fnRelease,
117 };
118
119
120 void QUARTZ_IUnkInit( QUARTZ_IUnkImpl* pImpl, IUnknown* punkOuter )
121 {
122         TRACE("(%p)\n",pImpl);
123
124         ICOM_VTBL(pImpl) = &iunknown;
125         pImpl->pEntries = NULL;
126         pImpl->dwEntries = 0;
127         pImpl->pDelegationFirst = NULL;
128         pImpl->pOnFinalRelease = NULL;
129         pImpl->ref = 1;
130         pImpl->punkControl = (IUnknown*)pImpl;
131
132         /* for implementing aggregation. */
133         if ( punkOuter != NULL )
134                 pImpl->punkControl = punkOuter;
135 }
136
137 void QUARTZ_IUnkAddDelegation(
138         QUARTZ_IUnkImpl* pImpl, QUARTZ_IFDelegation* pDelegation )
139 {
140         pDelegation->pNext = pImpl->pDelegationFirst;
141         pImpl->pDelegationFirst = pDelegation;
142 }
143