1c2c66affSColin Finck /*
2c2c66affSColin Finck * Copyright 2009 Vincent Povirk for CodeWeavers
3c2c66affSColin Finck * Copyright 2013 Ludger Sprenker
4c2c66affSColin Finck *
5c2c66affSColin Finck * This library is free software; you can redistribute it and/or
6c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
7c2c66affSColin Finck * License as published by the Free Software Foundation; either
8c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
9c2c66affSColin Finck *
10c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
11c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13c2c66affSColin Finck * Lesser General Public License for more details.
14c2c66affSColin Finck *
15c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
16c2c66affSColin Finck * License along with this library; if not, write to the Free Software
17c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18c2c66affSColin Finck */
19c2c66affSColin Finck
20*ae80686dSAmine Khaldi #include "config.h"
21*ae80686dSAmine Khaldi
22*ae80686dSAmine Khaldi #include <stdarg.h>
23*ae80686dSAmine Khaldi
24*ae80686dSAmine Khaldi #define COBJMACROS
25*ae80686dSAmine Khaldi
26*ae80686dSAmine Khaldi #include "windef.h"
27*ae80686dSAmine Khaldi #include "winbase.h"
28*ae80686dSAmine Khaldi #include "objbase.h"
29*ae80686dSAmine Khaldi #include "wine/unicode.h"
30*ae80686dSAmine Khaldi
31c2c66affSColin Finck #include "wincodecs_private.h"
32c2c66affSColin Finck
33*ae80686dSAmine Khaldi #include "wine/debug.h"
34*ae80686dSAmine Khaldi
35*ae80686dSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
36*ae80686dSAmine Khaldi
37c2c66affSColin Finck typedef struct PropertyBag {
38c2c66affSColin Finck IPropertyBag2 IPropertyBag2_iface;
39c2c66affSColin Finck LONG ref;
40c2c66affSColin Finck UINT prop_count;
41c2c66affSColin Finck PROPBAG2 *properties;
42c2c66affSColin Finck VARIANT *values;
43c2c66affSColin Finck } PropertyBag;
44c2c66affSColin Finck
impl_from_IPropertyBag2(IPropertyBag2 * iface)45c2c66affSColin Finck static inline PropertyBag *impl_from_IPropertyBag2(IPropertyBag2 *iface)
46c2c66affSColin Finck {
47c2c66affSColin Finck return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag2_iface);
48c2c66affSColin Finck }
49c2c66affSColin Finck
PropertyBag_QueryInterface(IPropertyBag2 * iface,REFIID iid,void ** ppv)50c2c66affSColin Finck static HRESULT WINAPI PropertyBag_QueryInterface(IPropertyBag2 *iface, REFIID iid,
51c2c66affSColin Finck void **ppv)
52c2c66affSColin Finck {
53c2c66affSColin Finck PropertyBag *This = impl_from_IPropertyBag2(iface);
54c2c66affSColin Finck TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
55c2c66affSColin Finck
56c2c66affSColin Finck if (!ppv) return E_INVALIDARG;
57c2c66affSColin Finck
58c2c66affSColin Finck if (IsEqualIID(&IID_IUnknown, iid) ||
59c2c66affSColin Finck IsEqualIID(&IID_IPropertyBag2, iid))
60c2c66affSColin Finck {
61c2c66affSColin Finck *ppv = &This->IPropertyBag2_iface;
62c2c66affSColin Finck }
63c2c66affSColin Finck else
64c2c66affSColin Finck {
65c2c66affSColin Finck *ppv = NULL;
66c2c66affSColin Finck return E_NOINTERFACE;
67c2c66affSColin Finck }
68c2c66affSColin Finck
69c2c66affSColin Finck IUnknown_AddRef((IUnknown*)*ppv);
70c2c66affSColin Finck return S_OK;
71c2c66affSColin Finck }
72c2c66affSColin Finck
PropertyBag_AddRef(IPropertyBag2 * iface)73c2c66affSColin Finck static ULONG WINAPI PropertyBag_AddRef(IPropertyBag2 *iface)
74c2c66affSColin Finck {
75c2c66affSColin Finck PropertyBag *This = impl_from_IPropertyBag2(iface);
76c2c66affSColin Finck ULONG ref = InterlockedIncrement(&This->ref);
77c2c66affSColin Finck
78c2c66affSColin Finck TRACE("(%p) refcount=%u\n", iface, ref);
79c2c66affSColin Finck
80c2c66affSColin Finck return ref;
81c2c66affSColin Finck }
82c2c66affSColin Finck
PropertyBag_Release(IPropertyBag2 * iface)83c2c66affSColin Finck static ULONG WINAPI PropertyBag_Release(IPropertyBag2 *iface)
84c2c66affSColin Finck {
85c2c66affSColin Finck PropertyBag *This = impl_from_IPropertyBag2(iface);
86c2c66affSColin Finck ULONG ref = InterlockedDecrement(&This->ref);
87c2c66affSColin Finck
88c2c66affSColin Finck TRACE("(%p) refcount=%u\n", iface, ref);
89c2c66affSColin Finck
90c2c66affSColin Finck if (ref == 0)
91c2c66affSColin Finck {
92c2c66affSColin Finck ULONG i;
93c2c66affSColin Finck if (This->properties && This->values)
94c2c66affSColin Finck {
95c2c66affSColin Finck for (i=0; i < This->prop_count; i++)
96c2c66affSColin Finck {
97c2c66affSColin Finck CoTaskMemFree(This->properties[i].pstrName);
98c2c66affSColin Finck VariantClear( This->values+i );
99c2c66affSColin Finck }
100c2c66affSColin Finck }
101c2c66affSColin Finck
102c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->properties);
103c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->values);
104c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This);
105c2c66affSColin Finck }
106c2c66affSColin Finck
107c2c66affSColin Finck return ref;
108c2c66affSColin Finck }
109c2c66affSColin Finck
find_item(PropertyBag * This,LPCOLESTR name)110c2c66affSColin Finck static LONG find_item(PropertyBag *This, LPCOLESTR name)
111c2c66affSColin Finck {
112c2c66affSColin Finck LONG i;
113c2c66affSColin Finck if (!This->properties)
114c2c66affSColin Finck return -1;
115c2c66affSColin Finck if (!name)
116c2c66affSColin Finck return -1;
117c2c66affSColin Finck
118c2c66affSColin Finck for (i=0; i < This->prop_count; i++)
119c2c66affSColin Finck {
120c2c66affSColin Finck if (strcmpW(name, This->properties[i].pstrName) == 0)
121c2c66affSColin Finck return i;
122c2c66affSColin Finck }
123c2c66affSColin Finck
124c2c66affSColin Finck return -1;
125c2c66affSColin Finck }
126c2c66affSColin Finck
PropertyBag_Read(IPropertyBag2 * iface,ULONG cProperties,PROPBAG2 * pPropBag,IErrorLog * pErrLog,VARIANT * pvarValue,HRESULT * phrError)127c2c66affSColin Finck static HRESULT WINAPI PropertyBag_Read(IPropertyBag2 *iface, ULONG cProperties,
128c2c66affSColin Finck PROPBAG2 *pPropBag, IErrorLog *pErrLog, VARIANT *pvarValue, HRESULT *phrError)
129c2c66affSColin Finck {
130c2c66affSColin Finck HRESULT res = S_OK;
131c2c66affSColin Finck ULONG i;
132c2c66affSColin Finck PropertyBag *This = impl_from_IPropertyBag2(iface);
133c2c66affSColin Finck
134c2c66affSColin Finck TRACE("(%p,%u,%p,%p,%p,%p)\n", iface, cProperties, pPropBag, pErrLog, pvarValue, phrError);
135c2c66affSColin Finck
136c2c66affSColin Finck for (i=0; i < cProperties; i++)
137c2c66affSColin Finck {
138c2c66affSColin Finck LONG idx;
139c2c66affSColin Finck if (pPropBag[i].dwHint && pPropBag[i].dwHint <= This->prop_count)
140c2c66affSColin Finck idx = pPropBag[i].dwHint-1;
141c2c66affSColin Finck else
142c2c66affSColin Finck idx = find_item(This, pPropBag[i].pstrName);
143c2c66affSColin Finck
144c2c66affSColin Finck if (idx > -1)
145c2c66affSColin Finck {
146c2c66affSColin Finck VariantInit(pvarValue+i);
147c2c66affSColin Finck res = VariantCopy(pvarValue+i, This->values+idx);
148c2c66affSColin Finck if (FAILED(res))
149c2c66affSColin Finck break;
150c2c66affSColin Finck phrError[i] = res;
151c2c66affSColin Finck }
152c2c66affSColin Finck else
153c2c66affSColin Finck {
154c2c66affSColin Finck res = E_FAIL;
155c2c66affSColin Finck break;
156c2c66affSColin Finck }
157c2c66affSColin Finck }
158c2c66affSColin Finck
159c2c66affSColin Finck return res;
160c2c66affSColin Finck }
161c2c66affSColin Finck
PropertyBag_Write(IPropertyBag2 * iface,ULONG cProperties,PROPBAG2 * pPropBag,VARIANT * pvarValue)162c2c66affSColin Finck static HRESULT WINAPI PropertyBag_Write(IPropertyBag2 *iface, ULONG cProperties,
163c2c66affSColin Finck PROPBAG2 *pPropBag, VARIANT *pvarValue)
164c2c66affSColin Finck {
165c2c66affSColin Finck HRESULT res = S_OK;
166c2c66affSColin Finck ULONG i;
167c2c66affSColin Finck PropertyBag *This = impl_from_IPropertyBag2(iface);
168c2c66affSColin Finck
169c2c66affSColin Finck TRACE("(%p,%u,%p,%p)\n", iface, cProperties, pPropBag, pvarValue);
170c2c66affSColin Finck
171c2c66affSColin Finck for (i=0; i < cProperties; i++)
172c2c66affSColin Finck {
173c2c66affSColin Finck LONG idx;
174c2c66affSColin Finck if (pPropBag[i].dwHint && pPropBag[i].dwHint <= This->prop_count)
175c2c66affSColin Finck idx = pPropBag[i].dwHint-1;
176c2c66affSColin Finck else
177c2c66affSColin Finck idx = find_item(This, pPropBag[i].pstrName);
178c2c66affSColin Finck
179c2c66affSColin Finck if (idx > -1)
180c2c66affSColin Finck {
181c2c66affSColin Finck if (This->properties[idx].vt != V_VT(pvarValue+i))
182c2c66affSColin Finck return WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE;
183c2c66affSColin Finck res = VariantCopy(This->values+idx, pvarValue+i);
184c2c66affSColin Finck if (FAILED(res))
185c2c66affSColin Finck return E_FAIL;
186c2c66affSColin Finck }
187c2c66affSColin Finck else
188c2c66affSColin Finck {
189c2c66affSColin Finck if (pPropBag[i].pstrName)
190c2c66affSColin Finck FIXME("Application tried to set the unknown option %s.\n",
191c2c66affSColin Finck debugstr_w(pPropBag[i].pstrName));
192c2c66affSColin Finck
193c2c66affSColin Finck /* FIXME: Function is not atomar on error, but MSDN does not say anything about it
194c2c66affSColin Finck * (no reset of items between 0 and i-1) */
195c2c66affSColin Finck return E_FAIL;
196c2c66affSColin Finck }
197c2c66affSColin Finck }
198c2c66affSColin Finck
199c2c66affSColin Finck return res;
200c2c66affSColin Finck }
201c2c66affSColin Finck
PropertyBag_CountProperties(IPropertyBag2 * iface,ULONG * pcProperties)202c2c66affSColin Finck static HRESULT WINAPI PropertyBag_CountProperties(IPropertyBag2 *iface, ULONG *pcProperties)
203c2c66affSColin Finck {
204c2c66affSColin Finck PropertyBag *This = impl_from_IPropertyBag2(iface);
205c2c66affSColin Finck
206c2c66affSColin Finck TRACE("(%p,%p)\n", iface, pcProperties);
207c2c66affSColin Finck
208c2c66affSColin Finck if (!pcProperties)
209c2c66affSColin Finck return E_INVALIDARG;
210c2c66affSColin Finck
211c2c66affSColin Finck *pcProperties = This->prop_count;
212c2c66affSColin Finck
213c2c66affSColin Finck return S_OK;
214c2c66affSColin Finck }
215c2c66affSColin Finck
copy_propbag2(PROPBAG2 * dest,const PROPBAG2 * src)216*ae80686dSAmine Khaldi static HRESULT copy_propbag2(PROPBAG2 *dest, const PROPBAG2 *src)
217c2c66affSColin Finck {
218c2c66affSColin Finck dest->cfType = src->cfType;
219c2c66affSColin Finck dest->clsid = src->clsid;
220c2c66affSColin Finck dest->dwHint = src->dwHint;
221c2c66affSColin Finck dest->dwType = src->dwType;
222c2c66affSColin Finck dest->vt = src->vt;
223c2c66affSColin Finck dest->pstrName = CoTaskMemAlloc((strlenW(src->pstrName)+1) * sizeof(WCHAR));
224c2c66affSColin Finck if(!dest->pstrName)
225c2c66affSColin Finck return E_OUTOFMEMORY;
226c2c66affSColin Finck
227c2c66affSColin Finck strcpyW(dest->pstrName, src->pstrName);
228c2c66affSColin Finck
229c2c66affSColin Finck return S_OK;
230c2c66affSColin Finck }
231c2c66affSColin Finck
PropertyBag_GetPropertyInfo(IPropertyBag2 * iface,ULONG iProperty,ULONG cProperties,PROPBAG2 * pPropBag,ULONG * pcProperties)232c2c66affSColin Finck static HRESULT WINAPI PropertyBag_GetPropertyInfo(IPropertyBag2 *iface, ULONG iProperty,
233c2c66affSColin Finck ULONG cProperties, PROPBAG2 *pPropBag, ULONG *pcProperties)
234c2c66affSColin Finck {
235c2c66affSColin Finck HRESULT res = S_OK;
236c2c66affSColin Finck ULONG i;
237c2c66affSColin Finck PropertyBag *This = impl_from_IPropertyBag2(iface);
238c2c66affSColin Finck
239c2c66affSColin Finck TRACE("(%p,%u,%u,%p,%p)\n", iface, iProperty, cProperties, pPropBag, pcProperties);
240c2c66affSColin Finck
241c2c66affSColin Finck if (iProperty >= This->prop_count && iProperty > 0)
242c2c66affSColin Finck return WINCODEC_ERR_VALUEOUTOFRANGE;
243c2c66affSColin Finck if (iProperty+cProperties > This->prop_count )
244c2c66affSColin Finck return WINCODEC_ERR_VALUEOUTOFRANGE;
245c2c66affSColin Finck
246c2c66affSColin Finck *pcProperties = min(cProperties, This->prop_count-iProperty);
247c2c66affSColin Finck
248c2c66affSColin Finck for (i=0; i < *pcProperties; i++)
249c2c66affSColin Finck {
250c2c66affSColin Finck res = copy_propbag2(pPropBag+i, This->properties+iProperty+i);
251c2c66affSColin Finck if (FAILED(res))
252c2c66affSColin Finck {
253c2c66affSColin Finck do {
254c2c66affSColin Finck CoTaskMemFree( pPropBag[--i].pstrName );
255c2c66affSColin Finck } while (i);
256c2c66affSColin Finck break;
257c2c66affSColin Finck }
258c2c66affSColin Finck }
259c2c66affSColin Finck
260c2c66affSColin Finck return res;
261c2c66affSColin Finck }
262c2c66affSColin Finck
PropertyBag_LoadObject(IPropertyBag2 * iface,LPCOLESTR pstrName,DWORD dwHint,IUnknown * pUnkObject,IErrorLog * pErrLog)263c2c66affSColin Finck static HRESULT WINAPI PropertyBag_LoadObject(IPropertyBag2 *iface, LPCOLESTR pstrName,
264c2c66affSColin Finck DWORD dwHint, IUnknown *pUnkObject, IErrorLog *pErrLog)
265c2c66affSColin Finck {
266c2c66affSColin Finck FIXME("(%p,%s,%u,%p,%p): stub\n", iface, debugstr_w(pstrName), dwHint, pUnkObject, pErrLog);
267c2c66affSColin Finck return E_NOTIMPL;
268c2c66affSColin Finck }
269c2c66affSColin Finck
270c2c66affSColin Finck static const IPropertyBag2Vtbl PropertyBag_Vtbl = {
271c2c66affSColin Finck PropertyBag_QueryInterface,
272c2c66affSColin Finck PropertyBag_AddRef,
273c2c66affSColin Finck PropertyBag_Release,
274c2c66affSColin Finck PropertyBag_Read,
275c2c66affSColin Finck PropertyBag_Write,
276c2c66affSColin Finck PropertyBag_CountProperties,
277c2c66affSColin Finck PropertyBag_GetPropertyInfo,
278c2c66affSColin Finck PropertyBag_LoadObject
279c2c66affSColin Finck };
280c2c66affSColin Finck
CreatePropertyBag2(const PROPBAG2 * options,UINT count,IPropertyBag2 ** ppPropertyBag2)281*ae80686dSAmine Khaldi HRESULT CreatePropertyBag2(const PROPBAG2 *options, UINT count,
282c2c66affSColin Finck IPropertyBag2 **ppPropertyBag2)
283c2c66affSColin Finck {
284c2c66affSColin Finck UINT i;
285c2c66affSColin Finck HRESULT res = S_OK;
286c2c66affSColin Finck PropertyBag *This;
287c2c66affSColin Finck
288c2c66affSColin Finck This = HeapAlloc(GetProcessHeap(), 0, sizeof(PropertyBag));
289c2c66affSColin Finck if (!This) return E_OUTOFMEMORY;
290c2c66affSColin Finck
291c2c66affSColin Finck This->IPropertyBag2_iface.lpVtbl = &PropertyBag_Vtbl;
292c2c66affSColin Finck This->ref = 1;
293c2c66affSColin Finck This->prop_count = count;
294c2c66affSColin Finck
295c2c66affSColin Finck if (count == 0)
296c2c66affSColin Finck {
297c2c66affSColin Finck This->properties = NULL;
298c2c66affSColin Finck This->values = NULL;
299c2c66affSColin Finck }
300c2c66affSColin Finck else
301c2c66affSColin Finck {
302c2c66affSColin Finck This->properties = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PROPBAG2)*count);
303c2c66affSColin Finck This->values = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VARIANT)*count);
304c2c66affSColin Finck
305c2c66affSColin Finck if (!This->properties || !This->values)
306c2c66affSColin Finck res = E_OUTOFMEMORY;
307c2c66affSColin Finck else
308c2c66affSColin Finck for (i=0; i < count; i++)
309c2c66affSColin Finck {
310c2c66affSColin Finck res = copy_propbag2(This->properties+i, options+i);
311c2c66affSColin Finck if (FAILED(res))
312c2c66affSColin Finck break;
313c2c66affSColin Finck This->properties[i].dwHint = i+1; /* 0 means unset, so we start with 1 */
314c2c66affSColin Finck }
315c2c66affSColin Finck }
316c2c66affSColin Finck
317c2c66affSColin Finck if (FAILED(res))
318c2c66affSColin Finck {
319c2c66affSColin Finck PropertyBag_Release(&This->IPropertyBag2_iface);
320c2c66affSColin Finck *ppPropertyBag2 = NULL;
321c2c66affSColin Finck }
322c2c66affSColin Finck else
323c2c66affSColin Finck *ppPropertyBag2 = &This->IPropertyBag2_iface;
324c2c66affSColin Finck
325c2c66affSColin Finck return res;
326c2c66affSColin Finck }
327