win32u: Move NtUserTranslateMessage implementation from user32.
[wine.git] / dlls / msxml3 / mxnamespace.c
blob518897af8e9bfed064ebee7627982130ddf39a61
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
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "ole2.h"
29 #include "msxml6.h"
31 #include "msxml_dispex.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
37 struct ns
39 BSTR prefix;
40 BSTR uri;
43 struct nscontext
45 struct list entry;
47 struct ns *ns;
48 int count;
49 int max_alloc;
52 #define DEFAULT_PREFIX_ALLOC_COUNT 16
54 static const WCHAR xmlW[] = {'x','m','l',0};
55 static const WCHAR xmluriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g',
56 '/','X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0};
58 typedef struct
60 DispatchEx dispex;
61 IMXNamespaceManager IMXNamespaceManager_iface;
62 IVBMXNamespaceManager IVBMXNamespaceManager_iface;
63 LONG ref;
65 struct list ctxts;
67 VARIANT_BOOL override;
68 } namespacemanager;
70 static inline namespacemanager *impl_from_IMXNamespaceManager( IMXNamespaceManager *iface )
72 return CONTAINING_RECORD(iface, namespacemanager, IMXNamespaceManager_iface);
75 static inline namespacemanager *impl_from_IVBMXNamespaceManager( IVBMXNamespaceManager *iface )
77 return CONTAINING_RECORD(iface, namespacemanager, IVBMXNamespaceManager_iface);
80 static HRESULT declare_prefix(namespacemanager *This, const WCHAR *prefix, const WCHAR *uri)
82 struct nscontext *ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
83 static const WCHAR emptyW[] = {0};
84 struct ns *ns;
85 int i;
87 if (ctxt->count == ctxt->max_alloc)
89 ctxt->max_alloc *= 2;
90 ctxt->ns = heap_realloc(ctxt->ns, ctxt->max_alloc*sizeof(*ctxt->ns));
93 if (!prefix) prefix = emptyW;
95 ns = NULL;
96 for (i = 0; i < ctxt->count; i++)
97 if (!wcscmp(ctxt->ns[i].prefix, prefix))
99 ns = &ctxt->ns[i];
100 break;
103 if (ns)
105 if (This->override == VARIANT_TRUE)
107 SysFreeString(ns->uri);
108 ns->uri = SysAllocString(uri);
109 return S_FALSE;
111 else
112 return E_FAIL;
114 else
116 ctxt->ns[ctxt->count].prefix = SysAllocString(prefix);
117 ctxt->ns[ctxt->count].uri = SysAllocString(uri);
118 ctxt->count++;
121 return S_OK;
124 /* returned stored pointer, caller needs to copy it */
125 static HRESULT get_declared_prefix_idx(const struct nscontext *ctxt, LONG index, BSTR *prefix)
127 *prefix = NULL;
129 if (index >= ctxt->count || index < 0) return E_FAIL;
131 if (index > 0) index = ctxt->count - index;
132 *prefix = ctxt->ns[index].prefix;
134 return S_OK;
137 /* returned stored pointer, caller needs to copy it */
138 static HRESULT get_declared_prefix_uri(const struct list *ctxts, const WCHAR *uri, BSTR *prefix)
140 struct nscontext *ctxt;
142 LIST_FOR_EACH_ENTRY(ctxt, ctxts, struct nscontext, entry)
144 int i;
145 for (i = 0; i < ctxt->count; i++)
146 if (!wcscmp(ctxt->ns[i].uri, uri))
148 *prefix = ctxt->ns[i].prefix;
149 return S_OK;
153 *prefix = NULL;
154 return E_FAIL;
157 static HRESULT get_uri_from_prefix(const struct nscontext *ctxt, const WCHAR *prefix, BSTR *uri)
159 int i;
161 for (i = 0; i < ctxt->count; i++)
162 if (!wcscmp(ctxt->ns[i].prefix, prefix))
164 *uri = ctxt->ns[i].uri;
165 return S_OK;
168 *uri = NULL;
169 return S_FALSE;
172 static struct nscontext* alloc_ns_context(void)
174 struct nscontext *ctxt;
176 ctxt = heap_alloc(sizeof(*ctxt));
177 if (!ctxt) return NULL;
179 ctxt->count = 0;
180 ctxt->max_alloc = DEFAULT_PREFIX_ALLOC_COUNT;
181 ctxt->ns = heap_alloc(ctxt->max_alloc*sizeof(*ctxt->ns));
182 if (!ctxt->ns)
184 heap_free(ctxt);
185 return NULL;
188 /* first allocated prefix is always 'xml' */
189 ctxt->ns[0].prefix = SysAllocString(xmlW);
190 ctxt->ns[0].uri = SysAllocString(xmluriW);
191 ctxt->count++;
192 if (!ctxt->ns[0].prefix || !ctxt->ns[0].uri)
194 heap_free(ctxt->ns);
195 heap_free(ctxt);
196 return NULL;
199 return ctxt;
202 static void free_ns_context(struct nscontext *ctxt)
204 int i;
206 for (i = 0; i < ctxt->count; i++)
208 SysFreeString(ctxt->ns[i].prefix);
209 SysFreeString(ctxt->ns[i].uri);
212 heap_free(ctxt->ns);
213 heap_free(ctxt);
216 static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
218 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
219 return IVBMXNamespaceManager_QueryInterface(&This->IVBMXNamespaceManager_iface, riid, ppvObject);
222 static ULONG WINAPI namespacemanager_AddRef(IMXNamespaceManager *iface)
224 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
225 return IVBMXNamespaceManager_AddRef(&This->IVBMXNamespaceManager_iface);
228 static ULONG WINAPI namespacemanager_Release(IMXNamespaceManager *iface)
230 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
231 return IVBMXNamespaceManager_Release(&This->IVBMXNamespaceManager_iface);
234 static HRESULT WINAPI namespacemanager_putAllowOverride(IMXNamespaceManager *iface,
235 VARIANT_BOOL override)
237 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
238 return IVBMXNamespaceManager_put_allowOverride(&This->IVBMXNamespaceManager_iface, override);
241 static HRESULT WINAPI namespacemanager_getAllowOverride(IMXNamespaceManager *iface,
242 VARIANT_BOOL *override)
244 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
245 return IVBMXNamespaceManager_get_allowOverride(&This->IVBMXNamespaceManager_iface, override);
248 static HRESULT WINAPI namespacemanager_reset(IMXNamespaceManager *iface)
250 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
251 return IVBMXNamespaceManager_reset(&This->IVBMXNamespaceManager_iface);
254 static HRESULT WINAPI namespacemanager_pushContext(IMXNamespaceManager *iface)
256 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
257 return IVBMXNamespaceManager_pushContext(&This->IVBMXNamespaceManager_iface);
260 static HRESULT WINAPI namespacemanager_pushNodeContext(IMXNamespaceManager *iface,
261 IXMLDOMNode *node, VARIANT_BOOL deep)
263 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
264 return IVBMXNamespaceManager_pushNodeContext(&This->IVBMXNamespaceManager_iface, node, deep);
267 static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
269 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
270 return IVBMXNamespaceManager_popContext(&This->IVBMXNamespaceManager_iface);
273 static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
274 const WCHAR *prefix, const WCHAR *namespaceURI)
276 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
278 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
280 TRACE("(%p)->(%s %s)\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
282 if (prefix && (!wcscmp(prefix, xmlW) || !wcscmp(prefix, xmlnsW) || !namespaceURI))
283 return E_INVALIDARG;
285 return declare_prefix(This, prefix, namespaceURI);
288 static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
289 LONG index, WCHAR *prefix, int *prefix_len)
291 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
292 struct nscontext *ctxt;
293 HRESULT hr;
294 BSTR prfx;
296 TRACE("%p, %ld, %p, %p.\n", This, index, prefix, prefix_len);
298 if (!prefix_len) return E_POINTER;
300 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
301 hr = get_declared_prefix_idx(ctxt, index, &prfx);
302 if (hr != S_OK) return hr;
304 if (prefix)
306 if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
307 lstrcpyW(prefix, prfx);
310 *prefix_len = SysStringLen(prfx);
312 return S_OK;
315 static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
316 const WCHAR *uri, LONG index, WCHAR *prefix, int *prefix_len)
318 namespacemanager *manager = impl_from_IMXNamespaceManager(iface);
319 HRESULT hr;
320 BSTR prfx;
322 TRACE("%p, %s, %ld, %p, %p.\n", iface, debugstr_w(uri), index, prefix, prefix_len);
324 if (!uri || !*uri || !prefix_len) return E_INVALIDARG;
326 hr = get_declared_prefix_uri(&manager->ctxts, uri, &prfx);
327 if (hr == S_OK)
329 /* TODO: figure out what index argument is for */
330 if (index) return E_FAIL;
332 if (prefix)
334 if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
335 lstrcpyW(prefix, prfx);
338 *prefix_len = SysStringLen(prfx);
339 TRACE("prefix=%s\n", debugstr_w(prfx));
342 return hr;
345 static HRESULT WINAPI namespacemanager_getURI(IMXNamespaceManager *iface,
346 const WCHAR *prefix, IXMLDOMNode *node, WCHAR *uri, int *uri_len)
348 namespacemanager *This = impl_from_IMXNamespaceManager( iface );
349 struct nscontext *ctxt;
350 HRESULT hr;
351 BSTR urib;
353 TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_w(prefix), node, uri, uri_len);
355 if (!prefix) return E_INVALIDARG;
356 if (!uri_len) return E_POINTER;
358 if (node)
360 FIXME("namespaces from DOM node not supported\n");
361 return E_NOTIMPL;
364 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
365 hr = get_uri_from_prefix(ctxt, prefix, &urib);
366 if (hr == S_OK)
368 if (uri)
370 if (*uri_len < (INT)SysStringLen(urib)) return E_XML_BUFFERTOOSMALL;
371 lstrcpyW(uri, urib);
374 else
375 if (uri) *uri = 0;
377 *uri_len = SysStringLen(urib);
379 return hr;
382 static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl =
384 namespacemanager_QueryInterface,
385 namespacemanager_AddRef,
386 namespacemanager_Release,
387 namespacemanager_putAllowOverride,
388 namespacemanager_getAllowOverride,
389 namespacemanager_reset,
390 namespacemanager_pushContext,
391 namespacemanager_pushNodeContext,
392 namespacemanager_popContext,
393 namespacemanager_declarePrefix,
394 namespacemanager_getDeclaredPrefix,
395 namespacemanager_getPrefix,
396 namespacemanager_getURI
399 static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **obj)
401 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
402 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
404 if ( IsEqualGUID( riid, &IID_IMXNamespaceManager) ||
405 IsEqualGUID( riid, &IID_IUnknown) )
407 *obj = &This->IMXNamespaceManager_iface;
409 else if ( IsEqualGUID( riid, &IID_IVBMXNamespaceManager) ||
410 IsEqualGUID( riid, &IID_IDispatch) )
412 *obj = &This->IVBMXNamespaceManager_iface;
414 else if (dispex_query_interface(&This->dispex, riid, obj))
416 return *obj ? S_OK : E_NOINTERFACE;
418 else
420 TRACE("Unsupported interface %s\n", debugstr_guid(riid));
421 *obj = NULL;
422 return E_NOINTERFACE;
425 IVBMXNamespaceManager_AddRef( iface );
427 return S_OK;
430 static ULONG WINAPI vbnamespacemanager_AddRef(IVBMXNamespaceManager *iface)
432 namespacemanager *manager = impl_from_IVBMXNamespaceManager(iface);
433 ULONG ref = InterlockedIncrement(&manager->ref);
434 TRACE("%p, refcount %lu.\n", iface, ref);
435 return ref;
438 static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
440 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
441 ULONG ref = InterlockedDecrement( &This->ref );
443 TRACE("%p, refcount %lu.\n", iface, ref);
445 if (!ref)
447 struct nscontext *ctxt, *ctxt2;
449 LIST_FOR_EACH_ENTRY_SAFE(ctxt, ctxt2, &This->ctxts, struct nscontext, entry)
451 list_remove(&ctxt->entry);
452 free_ns_context(ctxt);
455 heap_free( This );
458 return ref;
461 static HRESULT WINAPI vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager *iface, UINT *pctinfo)
463 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
464 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
467 static HRESULT WINAPI vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager *iface, UINT iTInfo,
468 LCID lcid, ITypeInfo **ppTInfo)
470 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
471 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
472 iTInfo, lcid, ppTInfo);
475 static HRESULT WINAPI vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager *iface, REFIID riid,
476 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
478 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
479 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
480 riid, rgszNames, cNames, lcid, rgDispId);
483 static HRESULT WINAPI vbnamespacemanager_Invoke(IVBMXNamespaceManager *iface, DISPID dispIdMember, REFIID riid,
484 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
485 EXCEPINFO *pExcepInfo, UINT *puArgErr)
487 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
488 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
489 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
492 static HRESULT WINAPI vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager *iface,
493 VARIANT_BOOL override)
495 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
497 TRACE("(%p)->(%d)\n", This, override);
498 This->override = override;
500 return S_OK;
503 static HRESULT WINAPI vbnamespacemanager_get_allowOverride(IVBMXNamespaceManager *iface,
504 VARIANT_BOOL *override)
506 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
508 TRACE("(%p)->(%p)\n", This, override);
510 if (!override) return E_POINTER;
511 *override = This->override;
513 return S_OK;
516 static HRESULT WINAPI vbnamespacemanager_reset(IVBMXNamespaceManager *iface)
518 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
519 FIXME("(%p): stub\n", This);
520 return E_NOTIMPL;
523 static HRESULT WINAPI vbnamespacemanager_pushContext(IVBMXNamespaceManager *iface)
525 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
526 struct nscontext *ctxt;
528 TRACE("(%p)\n", This);
530 ctxt = alloc_ns_context();
531 if (!ctxt) return E_OUTOFMEMORY;
533 list_add_head(&This->ctxts, &ctxt->entry);
535 return S_OK;
538 static HRESULT WINAPI vbnamespacemanager_pushNodeContext(IVBMXNamespaceManager *iface,
539 IXMLDOMNode *node, VARIANT_BOOL deep)
541 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
542 FIXME("(%p)->(%p %d): stub\n", This, node, deep);
543 return E_NOTIMPL;
546 static HRESULT WINAPI vbnamespacemanager_popContext(IVBMXNamespaceManager *iface)
548 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
549 const struct list *next;
550 struct nscontext *ctxt;
552 TRACE("(%p)\n", This);
554 next = list_next(&This->ctxts, list_head(&This->ctxts));
555 if (!next) return E_FAIL;
557 ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
558 list_remove(list_head(&This->ctxts));
560 free_ns_context(ctxt);
562 return S_OK;
565 static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *iface,
566 BSTR prefix, BSTR namespaceURI)
568 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
569 return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
572 static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
573 IMXNamespacePrefixes** prefixes)
575 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
576 FIXME("(%p)->(%p): stub\n", This, prefixes);
577 return E_NOTIMPL;
580 static HRESULT WINAPI vbnamespacemanager_getPrefixes(IVBMXNamespaceManager *iface,
581 BSTR namespaceURI, IMXNamespacePrefixes** prefixes)
583 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
584 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), prefixes);
585 return E_NOTIMPL;
588 static HRESULT WINAPI vbnamespacemanager_getURI(IVBMXNamespaceManager *iface,
589 BSTR prefix, VARIANT* uri)
591 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
592 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(prefix), uri);
593 return E_NOTIMPL;
596 static HRESULT WINAPI vbnamespacemanager_getURIFromNode(IVBMXNamespaceManager *iface,
597 BSTR prefix, IXMLDOMNode *node, VARIANT *uri)
599 namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
600 FIXME("(%p)->(%s %p %p): stub\n", This, debugstr_w(prefix), node, uri);
601 return E_NOTIMPL;
604 static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
606 vbnamespacemanager_QueryInterface,
607 vbnamespacemanager_AddRef,
608 vbnamespacemanager_Release,
609 vbnamespacemanager_GetTypeInfoCount,
610 vbnamespacemanager_GetTypeInfo,
611 vbnamespacemanager_GetIDsOfNames,
612 vbnamespacemanager_Invoke,
613 vbnamespacemanager_put_allowOverride,
614 vbnamespacemanager_get_allowOverride,
615 vbnamespacemanager_reset,
616 vbnamespacemanager_pushContext,
617 vbnamespacemanager_pushNodeContext,
618 vbnamespacemanager_popContext,
619 vbnamespacemanager_declarePrefix,
620 vbnamespacemanager_getDeclaredPrefixes,
621 vbnamespacemanager_getPrefixes,
622 vbnamespacemanager_getURI,
623 vbnamespacemanager_getURIFromNode
626 static const tid_t namespacemanager_iface_tids[] = {
627 IVBMXNamespaceManager_tid,
631 static dispex_static_data_t namespacemanager_dispex = {
632 NULL,
633 IVBMXNamespaceManager_tid,
634 NULL,
635 namespacemanager_iface_tids
638 HRESULT MXNamespaceManager_create(void **obj)
640 namespacemanager *This;
641 struct nscontext *ctxt;
643 TRACE("(%p)\n", obj);
645 This = heap_alloc( sizeof (*This) );
646 if( !This )
647 return E_OUTOFMEMORY;
649 This->IMXNamespaceManager_iface.lpVtbl = &MXNamespaceManagerVtbl;
650 This->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
651 This->ref = 1;
652 init_dispex(&This->dispex, (IUnknown*)&This->IVBMXNamespaceManager_iface, &namespacemanager_dispex);
654 list_init(&This->ctxts);
655 ctxt = alloc_ns_context();
656 if (!ctxt)
658 heap_free(This);
659 return E_OUTOFMEMORY;
662 list_add_head(&This->ctxts, &ctxt->entry);
664 This->override = VARIANT_TRUE;
666 *obj = &This->IMXNamespaceManager_iface;
668 TRACE("returning iface %p\n", *obj);
670 return S_OK;