shell32: Avoid leaks and add parameter checks in SHCreateShellFolderView[Ex].
[wine.git] / dlls / msxml3 / mxnamespace.c
blob7ec3f6e2330cceb8c21e68dd67125757bea1ad1b
1 /*
2 * IMXNamespaceManager implementation
4 * Copyright 2011-2012 Nikolay Sivov for CodeWeavers
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.
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.
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
21 #define COBJMACROS
22 #define NONAMELESSUNION
24 #include "config.h"
26 #include <stdarg.h>
27 #ifdef HAVE_LIBXML2
28 # include <libxml/parser.h>
29 # include <libxml/xmlerror.h>
30 # include <libxml/encoding.h>
31 #endif
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winuser.h"
36 #include "ole2.h"
37 #include "msxml6.h"
39 #include "msxml_private.h"
41 #include "wine/debug.h"
42 #include "wine/list.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
46 struct ns
48 BSTR prefix;
49 BSTR uri;
52 struct nscontext
54 struct list entry;
56 struct ns *ns;
57 int count;
58 int max_alloc;
61 #define DEFAULT_PREFIX_ALLOC_COUNT 16
63 static const WCHAR xmlW[] = {'x','m','l',0};
64 static const WCHAR xmluriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g',
65 '/','X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0};
67 typedef struct
69 DispatchEx dispex;
70 IMXNamespaceManager IMXNamespaceManager_iface;
71 IVBMXNamespaceManager IVBMXNamespaceManager_iface;
72 LONG ref;
74 struct list ctxts;
76 VARIANT_BOOL override;
77 } namespacemanager;
79 static inline namespacemanager *impl_from_IMXNamespaceManager( IMXNamespaceManager *iface )
81 return CONTAINING_RECORD(iface, namespacemanager, IMXNamespaceManager_iface);
84 static inline namespacemanager *impl_from_IVBMXNamespaceManager( IVBMXNamespaceManager *iface )
86 return CONTAINING_RECORD(iface, namespacemanager, IVBMXNamespaceManager_iface);
89 static HRESULT declare_prefix(namespacemanager *This, const WCHAR *prefix, const WCHAR *uri)
91 struct nscontext *ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
92 static const WCHAR emptyW[] = {0};
93 struct ns *ns;
94 int i;
96 if (ctxt->count == ctxt->max_alloc)
98 ctxt->max_alloc *= 2;
99 ctxt->ns = heap_realloc(ctxt->ns, ctxt->max_alloc*sizeof(*ctxt->ns));
102 if (!prefix) prefix = emptyW;
104 ns = NULL;
105 for (i = 0; i < ctxt->count; i++)
106 if (!strcmpW(ctxt->ns[i].prefix, prefix))
108 ns = &ctxt->ns[i];
109 break;
112 if (ns)
114 if (This->override == VARIANT_TRUE)
116 SysFreeString(ns->uri);
117 ns->uri = SysAllocString(uri);
118 return S_FALSE;
120 else
121 return E_FAIL;
123 else
125 ctxt->ns[ctxt->count].prefix = SysAllocString(prefix);
126 ctxt->ns[ctxt->count].uri = SysAllocString(uri);
127 ctxt->count++;
130 return S_OK;
133 /* returned stored pointer, caller needs to copy it */
134 static HRESULT get_declared_prefix_idx(const struct nscontext *ctxt, LONG index, BSTR *prefix)
136 *prefix = NULL;
138 if (index >= ctxt->count || index < 0) return E_FAIL;
140 if (index > 0) index = ctxt->count - index;
141 *prefix = ctxt->ns[index].prefix;
143 return S_OK;
146 /* returned stored pointer, caller needs to copy it */
147 static HRESULT get_declared_prefix_uri(const struct list *ctxts, const WCHAR *uri, BSTR *prefix)
149 struct nscontext *ctxt;
151 LIST_FOR_EACH_ENTRY(ctxt, ctxts, struct nscontext, entry)
153 int i;
154 for (i = 0; i < ctxt->count; i++)
155 if (!strcmpW(ctxt->ns[i].uri, uri))
157 *prefix = ctxt->ns[i].prefix;
158 return S_OK;
162 *prefix = NULL;
163 return E_FAIL;
166 static HRESULT get_uri_from_prefix(const struct nscontext *ctxt, const WCHAR *prefix, BSTR *uri)
168 int i;
170 for (i = 0; i < ctxt->count; i++)
171 if (!strcmpW(ctxt->ns[i].prefix, prefix))
173 *uri = ctxt->ns[i].uri;
174 return S_OK;
177 *uri = NULL;
178 return S_FALSE;
181 static struct nscontext* alloc_ns_context(void)
183 struct nscontext *ctxt;
185 ctxt = heap_alloc(sizeof(*ctxt));
186 if (!ctxt) return NULL;
188 ctxt->count = 0;
189 ctxt->max_alloc = DEFAULT_PREFIX_ALLOC_COUNT;
190 ctxt->ns = heap_alloc(ctxt->max_alloc*sizeof(*ctxt->ns));
191 if (!ctxt->ns)
193 heap_free(ctxt);
194 return NULL;
197 /* first allocated prefix is always 'xml' */
198 ctxt->ns[0].prefix = SysAllocString(xmlW);
199 ctxt->ns[0].uri = SysAllocString(xmluriW);
200 ctxt->count++;
201 if (!ctxt->ns[0].prefix || !ctxt->ns[0].uri)
203 heap_free(ctxt->ns);
204 heap_free(ctxt);
205 return NULL;
208 return ctxt;
211 static void free_ns_context(struct nscontext *ctxt)
213 int i;
215 for (i = 0; i < ctxt->count; i++)
217 SysFreeString(ctxt->ns[i].prefix);
218 SysFreeString(ctxt->ns[i].uri);
221 heap_free(ctxt->ns);
222 heap_free(ctxt);
225 static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
227 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
228 return IVBMXNamespaceManager_QueryInterface(&This->IVBMXNamespaceManager_iface, riid, ppvObject);
231 static ULONG WINAPI namespacemanager_AddRef(IMXNamespaceManager *iface)
233 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
234 return IVBMXNamespaceManager_AddRef(&This->IVBMXNamespaceManager_iface);
237 static ULONG WINAPI namespacemanager_Release(IMXNamespaceManager *iface)
239 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
240 return IVBMXNamespaceManager_Release(&This->IVBMXNamespaceManager_iface);
243 static HRESULT WINAPI namespacemanager_putAllowOverride(IMXNamespaceManager *iface,
244 VARIANT_BOOL override)
246 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
247 return IVBMXNamespaceManager_put_allowOverride(&This->IVBMXNamespaceManager_iface, override);
250 static HRESULT WINAPI namespacemanager_getAllowOverride(IMXNamespaceManager *iface,
251 VARIANT_BOOL *override)
253 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
254 return IVBMXNamespaceManager_get_allowOverride(&This->IVBMXNamespaceManager_iface, override);
257 static HRESULT WINAPI namespacemanager_reset(IMXNamespaceManager *iface)
259 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
260 return IVBMXNamespaceManager_reset(&This->IVBMXNamespaceManager_iface);
263 static HRESULT WINAPI namespacemanager_pushContext(IMXNamespaceManager *iface)
265 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
266 return IVBMXNamespaceManager_pushContext(&This->IVBMXNamespaceManager_iface);
269 static HRESULT WINAPI namespacemanager_pushNodeContext(IMXNamespaceManager *iface,
270 IXMLDOMNode *node, VARIANT_BOOL deep)
272 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
273 return IVBMXNamespaceManager_pushNodeContext(&This->IVBMXNamespaceManager_iface, node, deep);
276 static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
278 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
279 return IVBMXNamespaceManager_popContext(&This->IVBMXNamespaceManager_iface);
282 static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
283 const WCHAR *prefix, const WCHAR *namespaceURI)
285 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
287 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
289 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
291 if (prefix && (!strcmpW(prefix, xmlW) || !strcmpW(prefix, xmlnsW) || !namespaceURI))
292 return E_INVALIDARG;
294 return declare_prefix(This, prefix, namespaceURI);
297 static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
298 LONG index, WCHAR *prefix, int *prefix_len)
300 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
301 struct nscontext *ctxt;
302 HRESULT hr;
303 BSTR prfx;
305 TRACE("(%p)->(%d %p %p)\n", This, index, prefix, prefix_len);
307 if (!prefix_len) return E_POINTER;
309 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
310 hr = get_declared_prefix_idx(ctxt, index, &prfx);
311 if (hr != S_OK) return hr;
313 if (prefix)
315 if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
316 strcpyW(prefix, prfx);
319 *prefix_len = SysStringLen(prfx);
321 return S_OK;
324 static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
325 const WCHAR *uri, LONG index, WCHAR *prefix, int *prefix_len)
327 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
328 HRESULT hr;
329 BSTR prfx;
331 TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(uri), index, prefix, prefix_len);
333 if (!uri || !*uri || !prefix_len) return E_INVALIDARG;
335 hr = get_declared_prefix_uri(&This->ctxts, uri, &prfx);
336 if (hr == S_OK)
338 /* TODO: figure out what index argument is for */
339 if (index) return E_FAIL;
341 if (prefix)
343 if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
344 strcpyW(prefix, prfx);
347 *prefix_len = SysStringLen(prfx);
348 TRACE("prefix=%s\n", debugstr_w(prfx));
351 return hr;
354 static HRESULT WINAPI namespacemanager_getURI(IMXNamespaceManager *iface,
355 const WCHAR *prefix, IXMLDOMNode *node, WCHAR *uri, int *uri_len)
357 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
358 struct nscontext *ctxt;
359 HRESULT hr;
360 BSTR urib;
362 TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_w(prefix), node, uri, uri_len);
364 if (!prefix) return E_INVALIDARG;
365 if (!uri_len) return E_POINTER;
367 if (node)
369 FIXME("namespaces from DOM node not supported\n");
370 return E_NOTIMPL;
373 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
374 hr = get_uri_from_prefix(ctxt, prefix, &urib);
375 if (hr == S_OK)
377 if (uri)
379 if (*uri_len < (INT)SysStringLen(urib)) return E_XML_BUFFERTOOSMALL;
380 strcpyW(uri, urib);
383 else
384 if (uri) *uri = 0;
386 *uri_len = SysStringLen(urib);
388 return hr;
391 static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl =
393 namespacemanager_QueryInterface,
394 namespacemanager_AddRef,
395 namespacemanager_Release,
396 namespacemanager_putAllowOverride,
397 namespacemanager_getAllowOverride,
398 namespacemanager_reset,
399 namespacemanager_pushContext,
400 namespacemanager_pushNodeContext,
401 namespacemanager_popContext,
402 namespacemanager_declarePrefix,
403 namespacemanager_getDeclaredPrefix,
404 namespacemanager_getPrefix,
405 namespacemanager_getURI
408 static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **obj)
410 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
411 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
413 if ( IsEqualGUID( riid, &IID_IMXNamespaceManager) ||
414 IsEqualGUID( riid, &IID_IUnknown) )
416 *obj = &This->IMXNamespaceManager_iface;
418 else if ( IsEqualGUID( riid, &IID_IVBMXNamespaceManager) ||
419 IsEqualGUID( riid, &IID_IDispatch) )
421 *obj = &This->IVBMXNamespaceManager_iface;
423 else if (dispex_query_interface(&This->dispex, riid, obj))
425 return *obj ? S_OK : E_NOINTERFACE;
427 else
429 TRACE("Unsupported interface %s\n", debugstr_guid(riid));
430 *obj = NULL;
431 return E_NOINTERFACE;
434 IVBMXNamespaceManager_AddRef( iface );
436 return S_OK;
439 static ULONG WINAPI vbnamespacemanager_AddRef(IVBMXNamespaceManager *iface)
441 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
442 ULONG ref = InterlockedIncrement( &This->ref );
443 TRACE("(%p)->(%u)\n", This, ref );
444 return ref;
447 static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
449 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
450 ULONG ref = InterlockedDecrement( &This->ref );
452 TRACE("(%p)->(%u)\n", This, ref );
454 if ( ref == 0 )
456 struct nscontext *ctxt, *ctxt2;
458 LIST_FOR_EACH_ENTRY_SAFE(ctxt, ctxt2, &This->ctxts, struct nscontext, entry)
460 list_remove(&ctxt->entry);
461 free_ns_context(ctxt);
464 release_dispex(&This->dispex);
465 heap_free( This );
468 return ref;
471 static HRESULT WINAPI vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager *iface, UINT *pctinfo)
473 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
474 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
477 static HRESULT WINAPI vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager *iface, UINT iTInfo,
478 LCID lcid, ITypeInfo **ppTInfo)
480 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
481 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
482 iTInfo, lcid, ppTInfo);
485 static HRESULT WINAPI vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager *iface, REFIID riid,
486 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
488 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
489 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
490 riid, rgszNames, cNames, lcid, rgDispId);
493 static HRESULT WINAPI vbnamespacemanager_Invoke(IVBMXNamespaceManager *iface, DISPID dispIdMember, REFIID riid,
494 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
495 EXCEPINFO *pExcepInfo, UINT *puArgErr)
497 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
498 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
499 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
502 static HRESULT WINAPI vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager *iface,
503 VARIANT_BOOL override)
505 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
507 TRACE("(%p)->(%d)\n", This, override);
508 This->override = override;
510 return S_OK;
513 static HRESULT WINAPI vbnamespacemanager_get_allowOverride(IVBMXNamespaceManager *iface,
514 VARIANT_BOOL *override)
516 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
518 TRACE("(%p)->(%p)\n", This, override);
520 if (!override) return E_POINTER;
521 *override = This->override;
523 return S_OK;
526 static HRESULT WINAPI vbnamespacemanager_reset(IVBMXNamespaceManager *iface)
528 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
529 FIXME("(%p): stub\n", This);
530 return E_NOTIMPL;
533 static HRESULT WINAPI vbnamespacemanager_pushContext(IVBMXNamespaceManager *iface)
535 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
536 struct nscontext *ctxt;
538 TRACE("(%p)\n", This);
540 ctxt = alloc_ns_context();
541 if (!ctxt) return E_OUTOFMEMORY;
543 list_add_head(&This->ctxts, &ctxt->entry);
545 return S_OK;
548 static HRESULT WINAPI vbnamespacemanager_pushNodeContext(IVBMXNamespaceManager *iface,
549 IXMLDOMNode *node, VARIANT_BOOL deep)
551 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
552 FIXME("(%p)->(%p %d): stub\n", This, node, deep);
553 return E_NOTIMPL;
556 static HRESULT WINAPI vbnamespacemanager_popContext(IVBMXNamespaceManager *iface)
558 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
559 const struct list *next;
560 struct nscontext *ctxt;
562 TRACE("(%p)\n", This);
564 next = list_next(&This->ctxts, list_head(&This->ctxts));
565 if (!next) return E_FAIL;
567 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
568 list_remove(list_head(&This->ctxts));
570 free_ns_context(ctxt);
572 return S_OK;
575 static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *iface,
576 BSTR prefix, BSTR namespaceURI)
578 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
579 return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
582 static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
583 IMXNamespacePrefixes** prefixes)
585 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
586 FIXME("(%p)->(%p): stub\n", This, prefixes);
587 return E_NOTIMPL;
590 static HRESULT WINAPI vbnamespacemanager_getPrefixes(IVBMXNamespaceManager *iface,
591 BSTR namespaceURI, IMXNamespacePrefixes** prefixes)
593 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
594 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), prefixes);
595 return E_NOTIMPL;
598 static HRESULT WINAPI vbnamespacemanager_getURI(IVBMXNamespaceManager *iface,
599 BSTR prefix, VARIANT* uri)
601 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
602 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(prefix), uri);
603 return E_NOTIMPL;
606 static HRESULT WINAPI vbnamespacemanager_getURIFromNode(IVBMXNamespaceManager *iface,
607 BSTR prefix, IXMLDOMNode *node, VARIANT *uri)
609 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
610 FIXME("(%p)->(%s %p %p): stub\n", This, debugstr_w(prefix), node, uri);
611 return E_NOTIMPL;
614 static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
616 vbnamespacemanager_QueryInterface,
617 vbnamespacemanager_AddRef,
618 vbnamespacemanager_Release,
619 vbnamespacemanager_GetTypeInfoCount,
620 vbnamespacemanager_GetTypeInfo,
621 vbnamespacemanager_GetIDsOfNames,
622 vbnamespacemanager_Invoke,
623 vbnamespacemanager_put_allowOverride,
624 vbnamespacemanager_get_allowOverride,
625 vbnamespacemanager_reset,
626 vbnamespacemanager_pushContext,
627 vbnamespacemanager_pushNodeContext,
628 vbnamespacemanager_popContext,
629 vbnamespacemanager_declarePrefix,
630 vbnamespacemanager_getDeclaredPrefixes,
631 vbnamespacemanager_getPrefixes,
632 vbnamespacemanager_getURI,
633 vbnamespacemanager_getURIFromNode
636 static const tid_t namespacemanager_iface_tids[] = {
637 IVBMXNamespaceManager_tid,
641 static dispex_static_data_t namespacemanager_dispex = {
642 NULL,
643 IVBMXNamespaceManager_tid,
644 NULL,
645 namespacemanager_iface_tids
648 HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
650 namespacemanager *This;
651 struct nscontext *ctxt;
653 TRACE("(%p, %p)\n", outer, obj);
655 This = heap_alloc( sizeof (*This) );
656 if( !This )
657 return E_OUTOFMEMORY;
659 This->IMXNamespaceManager_iface.lpVtbl = &MXNamespaceManagerVtbl;
660 This->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
661 This->ref = 1;
662 init_dispex(&This->dispex, (IUnknown*)&This->IVBMXNamespaceManager_iface, &namespacemanager_dispex);
664 list_init(&This->ctxts);
665 ctxt = alloc_ns_context();
666 if (!ctxt)
668 heap_free(This);
669 return E_OUTOFMEMORY;
672 list_add_head(&This->ctxts, &ctxt->entry);
674 This->override = VARIANT_TRUE;
676 *obj = &This->IMXNamespaceManager_iface;
678 TRACE("returning iface %p\n", *obj);
680 return S_OK;