dplayx: Introduce impl_from_IDirectPlayLobby3A().
[wine] / dlls / quartz / enumfilters.c
1 /*
2  * Implementation of IEnumFilters Interface
3  *
4  * Copyright 2004 Christian Costa
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 "quartz_private.h"
22
23 #include "wine/debug.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
26
27 typedef struct IEnumFiltersImpl
28 {
29     IEnumFilters IEnumFilters_iface;
30     LONG refCount;
31     IGraphVersion * pVersionSource;
32     LONG Version;
33     IBaseFilter *** pppFilters;
34     ULONG * pNumFilters;
35     ULONG uIndex;
36 } IEnumFiltersImpl;
37
38 static const struct IEnumFiltersVtbl IEnumFiltersImpl_Vtbl;
39
40 static inline IEnumFiltersImpl *impl_from_IEnumFilters(IEnumFilters *iface)
41 {
42     return CONTAINING_RECORD(iface, IEnumFiltersImpl, IEnumFilters_iface);
43 }
44
45 HRESULT IEnumFiltersImpl_Construct(IGraphVersion * pVersionSource, IBaseFilter *** pppFilters, ULONG * pNumFilters, IEnumFilters ** ppEnum)
46 {
47     /* Note: The incoming IBaseFilter interfaces are not AddRef'd here as in Windows,
48      * they should have been previously AddRef'd. */
49     IEnumFiltersImpl * pEnumFilters = CoTaskMemAlloc(sizeof(IEnumFiltersImpl));
50     HRESULT hr;
51     LONG currentVersion;
52
53     TRACE("(%p, %p, %p)\n", pppFilters, pNumFilters, ppEnum);
54
55     *ppEnum = NULL;
56
57     if (!pEnumFilters)
58     {
59         return E_OUTOFMEMORY;
60     }
61
62     pEnumFilters->IEnumFilters_iface.lpVtbl = &IEnumFiltersImpl_Vtbl;
63     pEnumFilters->refCount = 1;
64     pEnumFilters->uIndex = 0;
65     pEnumFilters->pNumFilters = pNumFilters;
66     pEnumFilters->pppFilters = pppFilters;
67     IGraphVersion_AddRef(pVersionSource);
68     pEnumFilters->pVersionSource = pVersionSource;
69
70     /* Store the current version of the graph */
71     hr = IGraphVersion_QueryVersion(pVersionSource, &currentVersion);
72     pEnumFilters->Version = (hr==S_OK) ? currentVersion : 0;
73
74     *ppEnum = &pEnumFilters->IEnumFilters_iface;
75     return S_OK;
76 }
77
78 static HRESULT WINAPI IEnumFiltersImpl_QueryInterface(IEnumFilters * iface, REFIID riid, LPVOID * ppv)
79 {
80     TRACE("(%p)->(%s, %p)\n", iface, qzdebugstr_guid(riid), ppv);
81
82     *ppv = NULL;
83
84     if (IsEqualIID(riid, &IID_IUnknown))
85         *ppv = iface;
86     else if (IsEqualIID(riid, &IID_IEnumFilters))
87         *ppv = iface;
88
89     if (*ppv)
90     {
91         IUnknown_AddRef((IUnknown *)(*ppv));
92         return S_OK;
93     }
94
95     FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
96
97     return E_NOINTERFACE;
98 }
99
100 static ULONG WINAPI IEnumFiltersImpl_AddRef(IEnumFilters * iface)
101 {
102     IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
103     ULONG refCount = InterlockedIncrement(&This->refCount);
104
105     TRACE("(%p)->()\n", iface);
106
107     return refCount;
108 }
109
110 static ULONG WINAPI IEnumFiltersImpl_Release(IEnumFilters * iface)
111 {
112     IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
113     ULONG refCount = InterlockedDecrement(&This->refCount);
114
115     TRACE("(%p)->()\n", iface);
116
117     if (!refCount)
118     {
119         IGraphVersion_Release(This->pVersionSource);
120         return 0;
121     }
122     else
123         return refCount;
124 }
125
126 static HRESULT WINAPI IEnumFiltersImpl_Next(IEnumFilters * iface, ULONG cFilters, IBaseFilter ** ppFilters, ULONG * pcFetched)
127 {
128     ULONG cFetched; 
129     ULONG i;
130     LONG currentVersion;
131     IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
132     HRESULT hr;
133
134     cFetched = min(*This->pNumFilters, This->uIndex + cFilters) - This->uIndex;
135
136     TRACE("(%p)->(%u, %p, %p)\n", iface, cFilters, ppFilters, pcFetched);
137
138     /* First of all check if the graph has changed */
139     hr = IGraphVersion_QueryVersion(This->pVersionSource, &currentVersion);
140     if (hr==S_OK && This->Version != currentVersion)
141         return VFW_E_ENUM_OUT_OF_SYNC;
142
143
144     if (!ppFilters)
145         return E_POINTER;
146
147     for (i = 0; i < cFetched; i++)
148     {
149         ppFilters[i] = (*This->pppFilters)[This->uIndex + i];
150         IBaseFilter_AddRef(ppFilters[i]);
151     }
152
153     This->uIndex += cFetched;
154
155     if (pcFetched)
156         *pcFetched = cFetched;
157
158     if (cFetched != cFilters)
159         return S_FALSE;
160     return S_OK;
161 }
162
163 static HRESULT WINAPI IEnumFiltersImpl_Skip(IEnumFilters * iface, ULONG cFilters)
164 {
165     IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
166
167     TRACE("(%p)->(%u)\n", iface, cFilters);
168
169     if (This->uIndex + cFilters < *This->pNumFilters)
170     {
171         This->uIndex += cFilters;
172         return S_OK;
173     }
174     return S_FALSE;
175 }
176
177 static HRESULT WINAPI IEnumFiltersImpl_Reset(IEnumFilters * iface)
178 {
179     IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
180     HRESULT hr;
181     LONG currentVersion;
182
183     TRACE("(%p)->()\n", iface);
184
185     This->uIndex = 0;
186     hr = IGraphVersion_QueryVersion(This->pVersionSource, &currentVersion);
187     if (!hr)
188         This->Version = currentVersion;
189     return S_OK;
190 }
191
192 static HRESULT WINAPI IEnumFiltersImpl_Clone(IEnumFilters * iface, IEnumFilters ** ppEnum)
193 {
194     HRESULT hr;
195     IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
196
197     TRACE("(%p)->(%p)\n", iface, ppEnum);
198
199     hr = IEnumFiltersImpl_Construct(This->pVersionSource, This->pppFilters, This->pNumFilters, ppEnum);
200     if (FAILED(hr))
201         return hr;
202     return IEnumFilters_Skip(*ppEnum, This->uIndex);
203 }
204
205 static const IEnumFiltersVtbl IEnumFiltersImpl_Vtbl =
206 {
207     IEnumFiltersImpl_QueryInterface,
208     IEnumFiltersImpl_AddRef,
209     IEnumFiltersImpl_Release,
210     IEnumFiltersImpl_Next,
211     IEnumFiltersImpl_Skip,
212     IEnumFiltersImpl_Reset,
213     IEnumFiltersImpl_Clone
214 };