xref: /reactos/dll/win32/mshtml/propbag.c (revision c2c66aff)
1 /*
2  * Copyright 2010 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "mshtml_private.h"
20 
21 typedef struct {
22     IPropertyBag  IPropertyBag_iface;
23     IPropertyBag2 IPropertyBag2_iface;
24 
25     LONG ref;
26 
27     struct list props;
28 } PropertyBag;
29 
30 typedef struct {
31     struct list entry;
32     WCHAR *name;
33     WCHAR *value;
34 } param_prop_t;
35 
free_prop(param_prop_t * prop)36 static void free_prop(param_prop_t *prop)
37 {
38     list_remove(&prop->entry);
39 
40     heap_free(prop->name);
41     heap_free(prop->value);
42     heap_free(prop);
43 }
44 
find_prop(PropertyBag * prop_bag,const WCHAR * name)45 static param_prop_t *find_prop(PropertyBag *prop_bag, const WCHAR *name)
46 {
47     param_prop_t *iter;
48 
49     LIST_FOR_EACH_ENTRY(iter, &prop_bag->props, param_prop_t, entry) {
50         if(!strcmpiW(iter->name, name))
51             return iter;
52     }
53 
54     return NULL;
55 }
56 
add_prop(PropertyBag * prop_bag,const WCHAR * name,const WCHAR * value)57 static HRESULT add_prop(PropertyBag *prop_bag, const WCHAR *name, const WCHAR *value)
58 {
59     param_prop_t *prop;
60 
61     if(!name || !value)
62         return S_OK;
63 
64     TRACE("%p %s %s\n", prop_bag, debugstr_w(name), debugstr_w(value));
65 
66     prop = heap_alloc(sizeof(*prop));
67     if(!prop)
68         return E_OUTOFMEMORY;
69 
70     prop->name = heap_strdupW(name);
71     prop->value = heap_strdupW(value);
72     if(!prop->name || !prop->value) {
73         list_init(&prop->entry);
74         free_prop(prop);
75         return E_OUTOFMEMORY;
76     }
77 
78     list_add_tail(&prop_bag->props, &prop->entry);
79     return S_OK;
80 }
81 
impl_from_IPropertyBag(IPropertyBag * iface)82 static inline PropertyBag *impl_from_IPropertyBag(IPropertyBag *iface)
83 {
84     return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag_iface);
85 }
86 
PropertyBag_QueryInterface(IPropertyBag * iface,REFIID riid,void ** ppv)87 static HRESULT WINAPI PropertyBag_QueryInterface(IPropertyBag *iface, REFIID riid, void **ppv)
88 {
89     PropertyBag *This = impl_from_IPropertyBag(iface);
90 
91     if(IsEqualGUID(&IID_IUnknown, riid)) {
92         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
93         *ppv = &This->IPropertyBag_iface;
94     }else if(IsEqualGUID(&IID_IPropertyBag, riid)) {
95         TRACE("(%p)->(IID_IPropertyBag %p)\n", This, ppv);
96         *ppv = &This->IPropertyBag_iface;
97     }else if(IsEqualGUID(&IID_IPropertyBag2, riid)) {
98         TRACE("(%p)->(IID_IPropertyBag2 %p)\n", This, ppv);
99         *ppv = &This->IPropertyBag2_iface;
100     }else {
101         WARN("Unsopported interface %s\n", debugstr_guid(riid));
102         *ppv = NULL;
103         return E_NOINTERFACE;
104     }
105 
106     IUnknown_AddRef((IUnknown*)*ppv);
107     return S_OK;
108 }
109 
PropertyBag_AddRef(IPropertyBag * iface)110 static ULONG WINAPI PropertyBag_AddRef(IPropertyBag *iface)
111 {
112     PropertyBag *This = impl_from_IPropertyBag(iface);
113     LONG ref = InterlockedIncrement(&This->ref);
114 
115     TRACE("(%p) ref=%d\n", This, ref);
116 
117     return ref;
118 }
119 
PropertyBag_Release(IPropertyBag * iface)120 static ULONG WINAPI PropertyBag_Release(IPropertyBag *iface)
121 {
122     PropertyBag *This = impl_from_IPropertyBag(iface);
123     LONG ref = InterlockedDecrement(&This->ref);
124 
125     TRACE("(%p) ref=%d\n", This, ref);
126 
127     if(!ref) {
128         while(!list_empty(&This->props))
129             free_prop(LIST_ENTRY(This->props.next, param_prop_t, entry));
130         heap_free(This);
131     }
132 
133     return ref;
134 }
135 
PropertyBag_Read(IPropertyBag * iface,LPCOLESTR pszPropName,VARIANT * pVar,IErrorLog * pErrorLog)136 static HRESULT WINAPI PropertyBag_Read(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
137 {
138     PropertyBag *This = impl_from_IPropertyBag(iface);
139     param_prop_t *prop;
140     VARIANT v;
141 
142     TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
143 
144     prop = find_prop(This, pszPropName);
145     if(!prop) {
146         TRACE("Not found\n");
147         return E_INVALIDARG;
148     }
149 
150     V_BSTR(&v) = SysAllocString(prop->value);
151     if(!V_BSTR(&v))
152         return E_OUTOFMEMORY;
153 
154     if(V_VT(pVar) != VT_BSTR) {
155         HRESULT hres;
156 
157         V_VT(&v) = VT_BSTR;
158         hres = VariantChangeType(pVar, &v, 0, V_VT(pVar));
159         SysFreeString(V_BSTR(&v));
160         return hres;
161     }
162 
163     V_BSTR(pVar) = V_BSTR(&v);
164     return S_OK;
165 }
166 
PropertyBag_Write(IPropertyBag * iface,LPCOLESTR pszPropName,VARIANT * pVar)167 static HRESULT WINAPI PropertyBag_Write(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar)
168 {
169     PropertyBag *This = impl_from_IPropertyBag(iface);
170     FIXME("(%p)->(%s %s)\n", This, debugstr_w(pszPropName), debugstr_variant(pVar));
171     return E_NOTIMPL;
172 }
173 
174 static const IPropertyBagVtbl PropertyBagVtbl = {
175     PropertyBag_QueryInterface,
176     PropertyBag_AddRef,
177     PropertyBag_Release,
178     PropertyBag_Read,
179     PropertyBag_Write
180 };
181 
impl_from_IPropertyBag2(IPropertyBag2 * iface)182 static inline PropertyBag *impl_from_IPropertyBag2(IPropertyBag2 *iface)
183 {
184     return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag2_iface);
185 }
186 
PropertyBag2_QueryInterface(IPropertyBag2 * iface,REFIID riid,void ** ppv)187 static HRESULT WINAPI PropertyBag2_QueryInterface(IPropertyBag2 *iface, REFIID riid, void **ppv)
188 {
189     PropertyBag *This = impl_from_IPropertyBag2(iface);
190     return IPropertyBag_QueryInterface(&This->IPropertyBag_iface, riid, ppv);
191 }
192 
PropertyBag2_AddRef(IPropertyBag2 * iface)193 static ULONG WINAPI PropertyBag2_AddRef(IPropertyBag2 *iface)
194 {
195     PropertyBag *This = impl_from_IPropertyBag2(iface);
196     return IPropertyBag_AddRef(&This->IPropertyBag_iface);
197 }
198 
PropertyBag2_Release(IPropertyBag2 * iface)199 static ULONG WINAPI PropertyBag2_Release(IPropertyBag2 *iface)
200 {
201     PropertyBag *This = impl_from_IPropertyBag2(iface);
202     return IPropertyBag_Release(&This->IPropertyBag_iface);
203 }
204 
PropertyBag2_Read(IPropertyBag2 * iface,ULONG cProperties,PROPBAG2 * pPropBag,IErrorLog * pErrLog,VARIANT * pvarValue,HRESULT * phrError)205 static HRESULT WINAPI PropertyBag2_Read(IPropertyBag2 *iface, ULONG cProperties, PROPBAG2 *pPropBag,
206         IErrorLog *pErrLog, VARIANT *pvarValue, HRESULT *phrError)
207 {
208     PropertyBag *This = impl_from_IPropertyBag2(iface);
209     FIXME("(%p)->(%d %p %p %p %p)\n", This, cProperties, pPropBag, pErrLog, pvarValue, phrError);
210     return E_NOTIMPL;
211 }
212 
PropertyBag2_Write(IPropertyBag2 * iface,ULONG cProperties,PROPBAG2 * pPropBag,VARIANT * pvarValue)213 static HRESULT WINAPI PropertyBag2_Write(IPropertyBag2 *iface, ULONG cProperties, PROPBAG2 *pPropBag, VARIANT *pvarValue)
214 {
215     PropertyBag *This = impl_from_IPropertyBag2(iface);
216     FIXME("(%p)->(%d %p %s)\n", This, cProperties, pPropBag, debugstr_variant(pvarValue));
217     return E_NOTIMPL;
218 }
219 
PropertyBag2_CountProperties(IPropertyBag2 * iface,ULONG * pcProperties)220 static HRESULT WINAPI PropertyBag2_CountProperties(IPropertyBag2 *iface, ULONG *pcProperties)
221 {
222     PropertyBag *This = impl_from_IPropertyBag2(iface);
223     FIXME("(%p)->(%p)\n", This, pcProperties);
224     return E_NOTIMPL;
225 }
226 
PropertyBag2_GetPropertyInfo(IPropertyBag2 * iface,ULONG iProperty,ULONG cProperties,PROPBAG2 * pPropBag,ULONG * pcProperties)227 static HRESULT WINAPI PropertyBag2_GetPropertyInfo(IPropertyBag2 *iface, ULONG iProperty, ULONG cProperties,
228         PROPBAG2 *pPropBag, ULONG *pcProperties)
229 {
230     PropertyBag *This = impl_from_IPropertyBag2(iface);
231     FIXME("(%p)->(%u %u %p %p)\n", This, iProperty, cProperties, pPropBag, pcProperties);
232     return E_NOTIMPL;
233 }
234 
PropertyBag2_LoadObject(IPropertyBag2 * iface,LPCOLESTR pstrName,DWORD dwHint,IUnknown * pUnkObject,IErrorLog * pErrLog)235 static HRESULT WINAPI PropertyBag2_LoadObject(IPropertyBag2 *iface, LPCOLESTR pstrName, DWORD dwHint,
236         IUnknown *pUnkObject, IErrorLog *pErrLog)
237 {
238     PropertyBag *This = impl_from_IPropertyBag2(iface);
239     FIXME("(%p)->(%s %x %p %p)\n", This, debugstr_w(pstrName), dwHint, pUnkObject, pErrLog);
240     return E_NOTIMPL;
241 }
242 
243 static const IPropertyBag2Vtbl PropertyBag2Vtbl = {
244     PropertyBag2_QueryInterface,
245     PropertyBag2_AddRef,
246     PropertyBag2_Release,
247     PropertyBag2_Read,
248     PropertyBag2_Write,
249     PropertyBag2_CountProperties,
250     PropertyBag2_GetPropertyInfo,
251     PropertyBag2_LoadObject
252 };
253 
fill_props(nsIDOMHTMLElement * nselem,PropertyBag * prop_bag)254 static HRESULT fill_props(nsIDOMHTMLElement *nselem, PropertyBag *prop_bag)
255 {
256     const PRUnichar *name, *value;
257     nsAString name_str, value_str;
258     nsIDOMHTMLCollection *params;
259     nsIDOMHTMLElement *param_elem;
260     UINT32 length, i;
261     nsIDOMNode *nsnode;
262     nsresult nsres;
263     HRESULT hres = S_OK;
264 
265     static const PRUnichar nameW[] = {'n','a','m','e',0};
266     static const PRUnichar paramW[] = {'p','a','r','a','m',0};
267     static const PRUnichar valueW[] = {'v','a','l','u','e',0};
268 
269     nsAString_InitDepend(&name_str, paramW);
270     nsres = nsIDOMHTMLElement_GetElementsByTagName(nselem, &name_str, &params);
271     nsAString_Finish(&name_str);
272     if(NS_FAILED(nsres))
273         return E_FAIL;
274 
275     nsres = nsIDOMHTMLCollection_GetLength(params, &length);
276     if(NS_FAILED(nsres))
277         length = 0;
278 
279     for(i=0; i < length; i++) {
280         nsres = nsIDOMHTMLCollection_Item(params, i, &nsnode);
281         if(NS_FAILED(nsres)) {
282             hres = E_FAIL;
283             break;
284         }
285 
286         nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMHTMLElement, (void**)&param_elem);
287         nsIDOMNode_Release(nsnode);
288         if(NS_FAILED(nsres)) {
289             hres = E_FAIL;
290             break;
291         }
292 
293         nsres = get_elem_attr_value(param_elem, nameW, &name_str, &name);
294         if(NS_SUCCEEDED(nsres)) {
295             nsres = get_elem_attr_value(param_elem, valueW, &value_str, &value);
296             if(NS_SUCCEEDED(nsres)) {
297                 hres = add_prop(prop_bag, name, value);
298                 nsAString_Finish(&value_str);
299             }
300 
301             nsAString_Finish(&name_str);
302         }
303 
304         nsIDOMHTMLElement_Release(param_elem);
305         if(FAILED(hres))
306             break;
307         if(NS_FAILED(nsres)) {
308             hres = E_FAIL;
309             break;
310         }
311     }
312 
313     nsIDOMHTMLCollection_Release(params);
314     return hres;
315 }
316 
create_param_prop_bag(nsIDOMHTMLElement * nselem,IPropertyBag ** ret)317 HRESULT create_param_prop_bag(nsIDOMHTMLElement *nselem, IPropertyBag **ret)
318 {
319     PropertyBag *prop_bag;
320     HRESULT hres;
321 
322     prop_bag = heap_alloc(sizeof(*prop_bag));
323     if(!prop_bag)
324         return E_OUTOFMEMORY;
325 
326     prop_bag->IPropertyBag_iface.lpVtbl  = &PropertyBagVtbl;
327     prop_bag->IPropertyBag2_iface.lpVtbl = &PropertyBag2Vtbl;
328     prop_bag->ref = 1;
329 
330     list_init(&prop_bag->props);
331     hres = fill_props(nselem, prop_bag);
332     if(FAILED(hres) || list_empty(&prop_bag->props)) {
333         IPropertyBag_Release(&prop_bag->IPropertyBag_iface);
334         *ret = NULL;
335         return hres;
336     }
337 
338     *ret = &prop_bag->IPropertyBag_iface;
339     return S_OK;
340 }
341