winealsa: Fix AudioRenderClient Get/ReleaseBuffer protocol.
[wine] / dlls / msxml3 / mxnamespace.c
1 /*
2  *    IMXNamespaceManager implementation
3  *
4  * Copyright 2011 Nikolay Sivov for CodeWeavers
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22 #define NONAMELESSUNION
23
24 #include "config.h"
25
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
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winuser.h"
36 #include "ole2.h"
37 #include "msxml6.h"
38
39 #include "msxml_private.h"
40
41 #include "wine/debug.h"
42 #include "wine/list.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
45
46 struct ns
47 {
48     BSTR prefix;
49     BSTR uri;
50 };
51
52 struct nscontext
53 {
54     struct list entry;
55
56     struct ns *ns;
57     int   count;
58     int   max_alloc;
59 };
60
61 #define DEFAULT_PREFIX_ALLOC_COUNT 16
62
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};
66
67 typedef struct
68 {
69     DispatchEx dispex;
70     IMXNamespaceManager   IMXNamespaceManager_iface;
71     IVBMXNamespaceManager IVBMXNamespaceManager_iface;
72     LONG ref;
73
74     struct list ctxts;
75
76     VARIANT_BOOL override;
77 } namespacemanager;
78
79 static inline namespacemanager *impl_from_IMXNamespaceManager( IMXNamespaceManager *iface )
80 {
81     return CONTAINING_RECORD(iface, namespacemanager, IMXNamespaceManager_iface);
82 }
83
84 static inline namespacemanager *impl_from_IVBMXNamespaceManager( IVBMXNamespaceManager *iface )
85 {
86     return CONTAINING_RECORD(iface, namespacemanager, IVBMXNamespaceManager_iface);
87 }
88
89 static HRESULT declare_prefix(namespacemanager *This, const WCHAR *prefix, const WCHAR *uri)
90 {
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;
95
96     if (ctxt->count == ctxt->max_alloc)
97     {
98         ctxt->max_alloc *= 2;
99         ctxt->ns = heap_realloc(ctxt->ns, ctxt->max_alloc*sizeof(*ctxt->ns));
100     }
101
102     if (!prefix) prefix = emptyW;
103
104     ns = NULL;
105     for (i = 0; i < ctxt->count; i++)
106         if (!strcmpW(ctxt->ns[i].prefix, prefix))
107         {
108             ns = &ctxt->ns[i];
109             break;
110         }
111
112     if (ns)
113     {
114         if (This->override == VARIANT_TRUE)
115         {
116             SysFreeString(ns->uri);
117             ns->uri = SysAllocString(uri);
118             return S_FALSE;
119         }
120         else
121             return E_FAIL;
122     }
123     else
124     {
125         ctxt->ns[ctxt->count].prefix = SysAllocString(prefix);
126         ctxt->ns[ctxt->count].uri = SysAllocString(uri);
127         ctxt->count++;
128     }
129
130     return S_OK;
131 }
132
133 /* returned stored pointer, caller needs to copy it */
134 static HRESULT get_declared_prefix_idx(const struct nscontext *ctxt, LONG index, BSTR *prefix)
135 {
136     *prefix = NULL;
137
138     if (index >= ctxt->count || index < 0) return E_FAIL;
139
140     if (index > 0) index = ctxt->count - index;
141     *prefix = ctxt->ns[index].prefix;
142
143     return S_OK;
144 }
145
146 static HRESULT get_uri_from_prefix(const struct nscontext *ctxt, const WCHAR *prefix, BSTR *uri)
147 {
148     int i;
149
150     for (i = 0; i < ctxt->count; i++)
151         if (!strcmpW(ctxt->ns[i].prefix, prefix))
152         {
153             *uri = ctxt->ns[i].uri;
154             return S_OK;
155         }
156
157     *uri = NULL;
158     return S_FALSE;
159 }
160
161 static struct nscontext* alloc_ns_context(void)
162 {
163     struct nscontext *ctxt;
164
165     ctxt = heap_alloc(sizeof(*ctxt));
166     if (!ctxt) return NULL;
167
168     ctxt->count = 0;
169     ctxt->max_alloc = DEFAULT_PREFIX_ALLOC_COUNT;
170     ctxt->ns = heap_alloc(ctxt->max_alloc*sizeof(*ctxt->ns));
171
172     /* first allocated prefix is always 'xml' */
173     ctxt->ns[0].prefix = SysAllocString(xmlW);
174     ctxt->ns[0].uri = SysAllocString(xmluriW);
175     ctxt->count++;
176
177     return ctxt;
178 }
179
180 static void free_ns_context(struct nscontext *ctxt)
181 {
182     int i;
183
184     for (i = 0; i < ctxt->count; i++)
185     {
186         SysFreeString(ctxt->ns[i].prefix);
187         SysFreeString(ctxt->ns[i].uri);
188     }
189
190     heap_free(ctxt->ns);
191     heap_free(ctxt);
192 }
193
194 static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
195 {
196     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
197     return IVBMXNamespaceManager_QueryInterface(&This->IVBMXNamespaceManager_iface, riid, ppvObject);
198 }
199
200 static ULONG WINAPI namespacemanager_AddRef(IMXNamespaceManager *iface)
201 {
202     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
203     return IVBMXNamespaceManager_AddRef(&This->IVBMXNamespaceManager_iface);
204 }
205
206 static ULONG WINAPI namespacemanager_Release(IMXNamespaceManager *iface)
207 {
208     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
209     return IVBMXNamespaceManager_Release(&This->IVBMXNamespaceManager_iface);
210 }
211
212 static HRESULT WINAPI namespacemanager_putAllowOverride(IMXNamespaceManager *iface,
213     VARIANT_BOOL override)
214 {
215     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
216     return IVBMXNamespaceManager_put_allowOverride(&This->IVBMXNamespaceManager_iface, override);
217 }
218
219 static HRESULT WINAPI namespacemanager_getAllowOverride(IMXNamespaceManager *iface,
220     VARIANT_BOOL *override)
221 {
222     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
223     return IVBMXNamespaceManager_get_allowOverride(&This->IVBMXNamespaceManager_iface, override);
224 }
225
226 static HRESULT WINAPI namespacemanager_reset(IMXNamespaceManager *iface)
227 {
228     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
229     return IVBMXNamespaceManager_reset(&This->IVBMXNamespaceManager_iface);
230 }
231
232 static HRESULT WINAPI namespacemanager_pushContext(IMXNamespaceManager *iface)
233 {
234     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
235     return IVBMXNamespaceManager_pushContext(&This->IVBMXNamespaceManager_iface);
236 }
237
238 static HRESULT WINAPI namespacemanager_pushNodeContext(IMXNamespaceManager *iface,
239     IXMLDOMNode *node, VARIANT_BOOL deep)
240 {
241     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
242     return IVBMXNamespaceManager_pushNodeContext(&This->IVBMXNamespaceManager_iface, node, deep);
243 }
244
245 static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
246 {
247     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
248     return IVBMXNamespaceManager_popContext(&This->IVBMXNamespaceManager_iface);
249 }
250
251 static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
252     const WCHAR *prefix, const WCHAR *namespaceURI)
253 {
254     static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
255
256     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
257
258     TRACE("(%p)->(%s %s)\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
259
260     if (prefix && (!strcmpW(prefix, xmlW) || !strcmpW(prefix, xmlnsW) || !namespaceURI))
261         return E_INVALIDARG;
262
263     return declare_prefix(This, prefix, namespaceURI);
264 }
265
266 static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
267     LONG index, WCHAR *prefix, int *prefix_len)
268 {
269     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
270     struct nscontext *ctxt;
271     HRESULT hr;
272     BSTR prfx;
273
274     TRACE("(%p)->(%d %p %p)\n", This, index, prefix, prefix_len);
275
276     if (!prefix_len) return E_POINTER;
277
278     ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
279     hr = get_declared_prefix_idx(ctxt, index, &prfx);
280     if (hr != S_OK) return hr;
281
282     if (prefix)
283     {
284         if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
285         strcpyW(prefix, prfx);
286     }
287
288     *prefix_len = SysStringLen(prfx);
289
290     return S_OK;
291 }
292
293 static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
294     const WCHAR *uri, LONG index, WCHAR *prefix, int *prefix_len)
295 {
296     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
297     FIXME("(%p)->(%s %d %p %p): stub\n", This, debugstr_w(uri), index, prefix, prefix_len);
298     return E_NOTIMPL;
299 }
300
301 static HRESULT WINAPI namespacemanager_getURI(IMXNamespaceManager *iface,
302     const WCHAR *prefix, IXMLDOMNode *node, WCHAR *uri, int *uri_len)
303 {
304     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
305     struct nscontext *ctxt;
306     HRESULT hr;
307     BSTR urib;
308
309     TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_w(prefix), node, uri, uri_len);
310
311     if (!prefix) return E_INVALIDARG;
312     if (!uri_len) return E_POINTER;
313
314     if (node)
315     {
316         FIXME("namespaces from DOM node not supported\n");
317         return E_NOTIMPL;
318     }
319
320     ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
321     hr = get_uri_from_prefix(ctxt, prefix, &urib);
322     if (hr == S_OK)
323     {
324         if (uri)
325         {
326            if (*uri_len < (INT)SysStringLen(urib)) return E_XML_BUFFERTOOSMALL;
327            strcpyW(uri, urib);
328         }
329     }
330     else
331         if (uri) *uri = 0;
332
333     *uri_len = SysStringLen(urib);
334
335     return hr;
336 }
337
338 static const struct IMXNamespaceManagerVtbl MXNamespaceManagerVtbl =
339 {
340     namespacemanager_QueryInterface,
341     namespacemanager_AddRef,
342     namespacemanager_Release,
343     namespacemanager_putAllowOverride,
344     namespacemanager_getAllowOverride,
345     namespacemanager_reset,
346     namespacemanager_pushContext,
347     namespacemanager_pushNodeContext,
348     namespacemanager_popContext,
349     namespacemanager_declarePrefix,
350     namespacemanager_getDeclaredPrefix,
351     namespacemanager_getPrefix,
352     namespacemanager_getURI
353 };
354
355 static HRESULT WINAPI vbnamespacemanager_QueryInterface(IVBMXNamespaceManager *iface, REFIID riid, void **obj)
356 {
357     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
358     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
359
360     if ( IsEqualGUID( riid, &IID_IMXNamespaceManager) ||
361          IsEqualGUID( riid, &IID_IUnknown) )
362     {
363         *obj = &This->IMXNamespaceManager_iface;
364     }
365     else if ( IsEqualGUID( riid, &IID_IVBMXNamespaceManager) ||
366               IsEqualGUID( riid, &IID_IDispatch) )
367     {
368         *obj = &This->IVBMXNamespaceManager_iface;
369     }
370     else if (dispex_query_interface(&This->dispex, riid, obj))
371     {
372         return *obj ? S_OK : E_NOINTERFACE;
373     }
374     else
375     {
376         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
377         *obj = NULL;
378         return E_NOINTERFACE;
379     }
380
381     IVBMXNamespaceManager_AddRef( iface );
382
383     return S_OK;
384 }
385
386 static ULONG WINAPI vbnamespacemanager_AddRef(IVBMXNamespaceManager *iface)
387 {
388     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
389     ULONG ref = InterlockedIncrement( &This->ref );
390     TRACE("(%p)->(%u)\n", This, ref );
391     return ref;
392 }
393
394 static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
395 {
396     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
397     ULONG ref = InterlockedDecrement( &This->ref );
398
399     TRACE("(%p)->(%u)\n", This, ref );
400
401     if ( ref == 0 )
402     {
403         struct nscontext *ctxt, *ctxt2;
404
405         LIST_FOR_EACH_ENTRY_SAFE(ctxt, ctxt2, &This->ctxts, struct nscontext, entry)
406         {
407             list_remove(&ctxt->entry);
408             free_ns_context(ctxt);
409         }
410
411         release_dispex(&This->dispex);
412         heap_free( This );
413     }
414
415     return ref;
416 }
417
418 static HRESULT WINAPI vbnamespacemanager_GetTypeInfoCount(IVBMXNamespaceManager *iface, UINT *pctinfo)
419 {
420     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
421     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
422 }
423
424 static HRESULT WINAPI vbnamespacemanager_GetTypeInfo(IVBMXNamespaceManager *iface, UINT iTInfo,
425         LCID lcid, ITypeInfo **ppTInfo)
426 {
427     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
428     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
429         iTInfo, lcid, ppTInfo);
430 }
431
432 static HRESULT WINAPI vbnamespacemanager_GetIDsOfNames(IVBMXNamespaceManager *iface, REFIID riid,
433         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
434 {
435     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
436     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
437         riid, rgszNames, cNames, lcid, rgDispId);
438 }
439
440 static HRESULT WINAPI vbnamespacemanager_Invoke(IVBMXNamespaceManager *iface, DISPID dispIdMember, REFIID riid,
441         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
442         EXCEPINFO *pExcepInfo, UINT *puArgErr)
443 {
444     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
445     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
446         dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
447 }
448
449 static HRESULT WINAPI vbnamespacemanager_put_allowOverride(IVBMXNamespaceManager *iface,
450     VARIANT_BOOL override)
451 {
452     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
453
454     TRACE("(%p)->(%d)\n", This, override);
455     This->override = override;
456
457     return S_OK;
458 }
459
460 static HRESULT WINAPI vbnamespacemanager_get_allowOverride(IVBMXNamespaceManager *iface,
461     VARIANT_BOOL *override)
462 {
463     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
464
465     TRACE("(%p)->(%p)\n", This, override);
466
467     if (!override) return E_POINTER;
468     *override = This->override;
469
470     return S_OK;
471 }
472
473 static HRESULT WINAPI vbnamespacemanager_reset(IVBMXNamespaceManager *iface)
474 {
475     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
476     FIXME("(%p): stub\n", This);
477     return E_NOTIMPL;
478 }
479
480 static HRESULT WINAPI vbnamespacemanager_pushContext(IVBMXNamespaceManager *iface)
481 {
482     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
483     FIXME("(%p): stub\n", This);
484     return E_NOTIMPL;
485 }
486
487 static HRESULT WINAPI vbnamespacemanager_pushNodeContext(IVBMXNamespaceManager *iface,
488     IXMLDOMNode *node, VARIANT_BOOL deep)
489 {
490     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
491     FIXME("(%p)->(%p %d): stub\n", This, node, deep);
492     return E_NOTIMPL;
493 }
494
495 static HRESULT WINAPI vbnamespacemanager_popContext(IVBMXNamespaceManager *iface)
496 {
497     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
498     FIXME("(%p): stub\n", This);
499     return E_NOTIMPL;
500 }
501
502 static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *iface,
503     BSTR prefix, BSTR namespaceURI)
504 {
505     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
506     return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
507 }
508
509 static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
510     IMXNamespacePrefixes** prefixes)
511 {
512     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
513     FIXME("(%p)->(%p): stub\n", This, prefixes);
514     return E_NOTIMPL;
515 }
516
517 static HRESULT WINAPI vbnamespacemanager_getPrefixes(IVBMXNamespaceManager *iface,
518     BSTR namespaceURI, IMXNamespacePrefixes** prefixes)
519 {
520     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
521     FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), prefixes);
522     return E_NOTIMPL;
523 }
524
525 static HRESULT WINAPI vbnamespacemanager_getURI(IVBMXNamespaceManager *iface,
526     BSTR prefix, VARIANT* uri)
527 {
528     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
529     FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(prefix), uri);
530     return E_NOTIMPL;
531 }
532
533 static HRESULT WINAPI vbnamespacemanager_getURIFromNode(IVBMXNamespaceManager *iface,
534     BSTR prefix, IXMLDOMNode *node, VARIANT *uri)
535 {
536     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
537     FIXME("(%p)->(%s %p %p): stub\n", This, debugstr_w(prefix), node, uri);
538     return E_NOTIMPL;
539 }
540
541 static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
542 {
543     vbnamespacemanager_QueryInterface,
544     vbnamespacemanager_AddRef,
545     vbnamespacemanager_Release,
546     vbnamespacemanager_GetTypeInfoCount,
547     vbnamespacemanager_GetTypeInfo,
548     vbnamespacemanager_GetIDsOfNames,
549     vbnamespacemanager_Invoke,
550     vbnamespacemanager_put_allowOverride,
551     vbnamespacemanager_get_allowOverride,
552     vbnamespacemanager_reset,
553     vbnamespacemanager_pushContext,
554     vbnamespacemanager_pushNodeContext,
555     vbnamespacemanager_popContext,
556     vbnamespacemanager_declarePrefix,
557     vbnamespacemanager_getDeclaredPrefixes,
558     vbnamespacemanager_getPrefixes,
559     vbnamespacemanager_getURI,
560     vbnamespacemanager_getURIFromNode
561 };
562
563 static const tid_t namespacemanager_iface_tids[] = {
564     IVBMXNamespaceManager_tid,
565     0
566 };
567 static dispex_static_data_t namespacemanager_dispex = {
568     NULL,
569     IVBMXNamespaceManager_tid,
570     NULL,
571     namespacemanager_iface_tids
572 };
573
574 HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
575 {
576     namespacemanager *This;
577     struct nscontext *ctxt;
578
579     TRACE("(%p, %p)\n", outer, obj);
580
581     This = heap_alloc( sizeof (*This) );
582     if( !This )
583         return E_OUTOFMEMORY;
584
585     This->IMXNamespaceManager_iface.lpVtbl = &MXNamespaceManagerVtbl;
586     This->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
587     This->ref = 1;
588     init_dispex(&This->dispex, (IUnknown*)&This->IVBMXNamespaceManager_iface, &namespacemanager_dispex);
589
590     list_init(&This->ctxts);
591     ctxt = alloc_ns_context();
592     list_add_head(&This->ctxts, &ctxt->entry);
593
594     This->override = VARIANT_TRUE;
595
596     *obj = &This->IMXNamespaceManager_iface;
597
598     TRACE("returning iface %p\n", *obj);
599
600     return S_OK;
601 }