Prevent crash when no URL is specified.
[wine] / dlls / quartz / enummedia.c
1 /*
2  * Implementation of IEnumMediaTypes Interface
3  *
4  * Copyright 2003 Robert Shearman
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 "quartz_private.h"
22
23 #include "wine/debug.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
26
27 HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc)
28 {
29     memcpy(pDest, pSrc, sizeof(AM_MEDIA_TYPE));
30     if (!(pDest->pbFormat = CoTaskMemAlloc(pSrc->cbFormat)))
31         return E_OUTOFMEMORY;
32     memcpy(pDest->pbFormat, pSrc->pbFormat, pSrc->cbFormat);
33     return S_OK;
34 }
35
36 void DeleteMediaType(AM_MEDIA_TYPE * pMediaType)
37 {
38     if (pMediaType->pbFormat)
39     {
40         CoTaskMemFree(pMediaType->pbFormat);
41         pMediaType->pbFormat = NULL;
42     }
43     if (pMediaType->pUnk)
44     {
45         IUnknown_Release(pMediaType->pUnk);
46         pMediaType->pUnk = NULL;
47     }
48 }
49
50 BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards)
51 {
52     TRACE("pmt1: ");
53     dump_AM_MEDIA_TYPE(pmt1);
54     TRACE("pmt2: ");
55     dump_AM_MEDIA_TYPE(pmt2);
56     return (((bWildcards && (IsEqualGUID(&pmt1->majortype, &GUID_NULL) || IsEqualGUID(&pmt2->majortype, &GUID_NULL))) || IsEqualGUID(&pmt1->majortype, &pmt2->majortype)) &&
57             ((bWildcards && (IsEqualGUID(&pmt1->subtype, &GUID_NULL)   || IsEqualGUID(&pmt2->subtype, &GUID_NULL)))   || IsEqualGUID(&pmt1->subtype, &pmt2->subtype)));
58 }
59
60 void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt)
61 {
62     if (!pmt)
63         return;
64     TRACE("\t%s\n\t%s\n\t...\n\t%s\n", qzdebugstr_guid(&pmt->majortype), qzdebugstr_guid(&pmt->subtype), qzdebugstr_guid(&pmt->formattype));
65 }
66
67 typedef struct IEnumMediaTypesImpl
68 {
69     const IEnumMediaTypesVtbl * lpVtbl;
70     ULONG refCount;
71     ENUMMEDIADETAILS enumMediaDetails;
72     ULONG uIndex;
73 } IEnumMediaTypesImpl;
74
75 static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl;
76
77 HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails, IEnumMediaTypes ** ppEnum)
78 {
79     ULONG i;
80     IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl));
81
82     if (!pEnumMediaTypes)
83     {
84         *ppEnum = NULL;
85         return E_OUTOFMEMORY;
86     }
87     pEnumMediaTypes->lpVtbl = &IEnumMediaTypesImpl_Vtbl;
88     pEnumMediaTypes->refCount = 1;
89     pEnumMediaTypes->uIndex = 0;
90     pEnumMediaTypes->enumMediaDetails.cMediaTypes = pDetails->cMediaTypes;
91     pEnumMediaTypes->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * pDetails->cMediaTypes);
92     for (i = 0; i < pDetails->cMediaTypes; i++)
93         pEnumMediaTypes->enumMediaDetails.pMediaTypes[i] = pDetails->pMediaTypes[i];
94     *ppEnum = (IEnumMediaTypes *)(&pEnumMediaTypes->lpVtbl);
95     return S_OK;
96 }
97
98 static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface, REFIID riid, LPVOID * ppv)
99 {
100     TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
101
102     *ppv = NULL;
103
104     if (IsEqualIID(riid, &IID_IUnknown))
105         *ppv = (LPVOID)iface;
106     else if (IsEqualIID(riid, &IID_IEnumMediaTypes))
107         *ppv = (LPVOID)iface;
108
109     if (*ppv)
110     {
111         IUnknown_AddRef((IUnknown *)(*ppv));
112         return S_OK;
113     }
114
115     FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
116
117     return E_NOINTERFACE;
118 }
119
120 static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface)
121 {
122     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
123     ULONG refCount = InterlockedIncrement(&This->refCount);
124
125     TRACE("()\n");
126
127     return refCount;
128 }
129
130 static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface)
131 {
132     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
133     ULONG refCount = InterlockedDecrement(&This->refCount);
134
135     TRACE("()\n");
136
137     if (!refCount)
138     {
139         CoTaskMemFree(This->enumMediaDetails.pMediaTypes);
140         CoTaskMemFree(This);
141         return 0;
142     }
143     else
144         return refCount;
145 }
146
147 static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched)
148 {
149     ULONG cFetched; 
150     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
151
152     cFetched = min(This->enumMediaDetails.cMediaTypes, This->uIndex + cMediaTypes) - This->uIndex;
153
154     TRACE("(%lu, %p, %p)\n", cMediaTypes, ppMediaTypes, pcFetched);
155     TRACE("Next uIndex: %lu, cFetched: %lu\n", This->uIndex, cFetched);
156
157     if (cFetched > 0)
158     {
159         ULONG i;
160         *ppMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * cFetched);
161         for (i = 0; i < cFetched; i++)
162             (*ppMediaTypes)[i] = This->enumMediaDetails.pMediaTypes[This->uIndex + i];
163     }
164
165     if ((cMediaTypes != 1) || pcFetched)
166         *pcFetched = cFetched;
167
168     This->uIndex += cFetched;
169
170     if (cFetched != cMediaTypes)
171         return S_FALSE;
172     return S_OK;
173 }
174
175 static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface, ULONG cMediaTypes)
176 {
177     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
178
179     TRACE("(%lu)\n", cMediaTypes);
180
181     if (This->uIndex + cMediaTypes < This->enumMediaDetails.cMediaTypes)
182     {
183         This->uIndex += cMediaTypes;
184         return S_OK;
185     }
186     return S_FALSE;
187 }
188
189 static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface)
190 {
191     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
192
193     TRACE("()\n");
194
195     This->uIndex = 0;
196     return S_OK;
197 }
198
199 static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface, IEnumMediaTypes ** ppEnum)
200 {
201     HRESULT hr;
202     IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
203
204     TRACE("(%p)\n", ppEnum);
205
206     hr = IEnumMediaTypesImpl_Construct(&This->enumMediaDetails, ppEnum);
207     if (FAILED(hr))
208         return hr;
209     return IEnumMediaTypes_Skip(*ppEnum, This->uIndex);
210 }
211
212 static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl =
213 {
214     IEnumMediaTypesImpl_QueryInterface,
215     IEnumMediaTypesImpl_AddRef,
216     IEnumMediaTypesImpl_Release,
217     IEnumMediaTypesImpl_Next,
218     IEnumMediaTypesImpl_Skip,
219     IEnumMediaTypesImpl_Reset,
220     IEnumMediaTypesImpl_Clone
221 };