Implement ResetDC and PHYSICALOFFSET[X|Y] devcaps.
[wine] / dlls / quartz / iunk.c
1 /*
2  * An implementation of IUnknown.
3  *
4  * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include "windef.h"
24 #include "winerror.h"
25 #include "winbase.h"
26 #include "wine/obj_base.h"
27
28 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
30
31 #include "quartz_private.h"
32 #include "iunk.h"
33
34
35 static HRESULT WINAPI
36 IUnknown_fnQueryInterface(IUnknown* iface,REFIID riid,LPVOID *ppobj)
37 {
38         ICOM_THIS(QUARTZ_IUnkImpl,iface);
39         size_t  ofs;
40         DWORD   dwIndex;
41         QUARTZ_IFDelegation*    pDelegation;
42         HRESULT hr;
43
44         TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
45
46         if ( ppobj == NULL )
47                 return E_POINTER;
48         *ppobj = NULL;
49
50         ofs = 0;
51
52         if ( IsEqualGUID( &IID_IUnknown, riid ) )
53         {
54                 TRACE("IID_IUnknown - returns inner object.\n");
55         }
56         else
57         {
58                 for ( dwIndex = 0; dwIndex < This->dwEntries; dwIndex++ )
59                 {
60                         if ( IsEqualGUID( This->pEntries[dwIndex].piid, riid ) )
61                         {
62                                 ofs = This->pEntries[dwIndex].ofsVTPtr;
63                                 break;
64                         }
65                 }
66                 if ( dwIndex == This->dwEntries )
67                 {
68                         hr = E_NOINTERFACE;
69
70                         /* delegation */
71                         pDelegation = This->pDelegationFirst;
72                         while ( pDelegation != NULL )
73                         {
74                                 hr = (*pDelegation->pOnQueryInterface)( iface, riid, ppobj );
75                                 if ( hr != E_NOINTERFACE )
76                                         break;
77                                 pDelegation = pDelegation->pNext;
78                         }
79
80                         if ( hr == E_NOINTERFACE )
81                         {
82                                 FIXME("(%p) unknown interface: %s\n",This,debugstr_guid(riid));
83                         }
84
85                         return hr;
86                 }
87         }
88
89         *ppobj = (LPVOID)(((char*)This) + ofs);
90         IUnknown_AddRef((IUnknown*)(*ppobj));
91
92         return S_OK;
93 }
94
95 static ULONG WINAPI
96 IUnknown_fnAddRef(IUnknown* iface)
97 {
98         ICOM_THIS(QUARTZ_IUnkImpl,iface);
99
100         TRACE("(%p)->()\n",This);
101
102         return InterlockedExchangeAdd(&(This->ref),1) + 1;
103 }
104
105 static ULONG WINAPI
106 IUnknown_fnRelease(IUnknown* iface)
107 {
108         ICOM_THIS(QUARTZ_IUnkImpl,iface);
109         LONG    ref;
110
111         TRACE("(%p)->()\n",This);
112         ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
113         if ( ref > 0 )
114                 return (ULONG)ref;
115
116         This->ref ++;
117         if ( This->pOnFinalRelease != NULL )
118                 (*(This->pOnFinalRelease))(iface);
119         This->ref --;
120
121         QUARTZ_FreeObj(This);
122
123         return 0;
124 }
125
126 static ICOM_VTABLE(IUnknown) iunknown =
127 {
128         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
129         /* IUnknown fields */
130         IUnknown_fnQueryInterface,
131         IUnknown_fnAddRef,
132         IUnknown_fnRelease,
133 };
134
135
136 void QUARTZ_IUnkInit( QUARTZ_IUnkImpl* pImpl, IUnknown* punkOuter )
137 {
138         TRACE("(%p)\n",pImpl);
139
140         ICOM_VTBL(pImpl) = &iunknown;
141         pImpl->pEntries = NULL;
142         pImpl->dwEntries = 0;
143         pImpl->pDelegationFirst = NULL;
144         pImpl->pOnFinalRelease = NULL;
145         pImpl->ref = 1;
146         pImpl->punkControl = (IUnknown*)pImpl;
147
148         /* for implementing aggregation. */
149         if ( punkOuter != NULL )
150                 pImpl->punkControl = punkOuter;
151 }
152
153 void QUARTZ_IUnkAddDelegation(
154         QUARTZ_IUnkImpl* pImpl, QUARTZ_IFDelegation* pDelegation )
155 {
156         pDelegation->pNext = pImpl->pDelegationFirst;
157         pImpl->pDelegationFirst = pDelegation;
158 }
159