dsound: Don't specify period size for the IAudioClient.
[wine] / dlls / msxml3 / element.c
1 /*
2  *    DOM Document implementation
3  *
4  * Copyright 2005 Mike McCormack
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
23 #include "config.h"
24
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 #endif
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "winnls.h"
35 #include "ole2.h"
36 #include "msxml6.h"
37
38 #include "msxml_private.h"
39
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43
44 #ifdef HAVE_LIBXML2
45
46 static const xmlChar DT_prefix[] = "dt";
47 static const xmlChar DT_nsURI[] = "urn:schemas-microsoft-com:datatypes";
48
49 typedef struct _domelem
50 {
51     xmlnode node;
52     IXMLDOMElement IXMLDOMElement_iface;
53     LONG ref;
54 } domelem;
55
56 static const struct nodemap_funcs domelem_attr_map;
57
58 static inline domelem *impl_from_IXMLDOMElement( IXMLDOMElement *iface )
59 {
60     return CONTAINING_RECORD(iface, domelem, IXMLDOMElement_iface);
61 }
62
63 static inline xmlNodePtr get_element( const domelem *This )
64 {
65     return This->node.node;
66 }
67
68 static HRESULT WINAPI domelem_QueryInterface(
69     IXMLDOMElement *iface,
70     REFIID riid,
71     void** ppvObject )
72 {
73     domelem *This = impl_from_IXMLDOMElement( iface );
74
75     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
76
77     if ( IsEqualGUID( riid, &IID_IXMLDOMElement ) ||
78          IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
79          IsEqualGUID( riid, &IID_IDispatch ) ||
80          IsEqualGUID( riid, &IID_IUnknown ) )
81     {
82         *ppvObject = &This->IXMLDOMElement_iface;
83     }
84     else if(node_query_interface(&This->node, riid, ppvObject))
85     {
86         return *ppvObject ? S_OK : E_NOINTERFACE;
87     }
88     else
89     {
90         TRACE("interface %s not implemented\n", debugstr_guid(riid));
91         *ppvObject = NULL;
92         return E_NOINTERFACE;
93     }
94
95     IUnknown_AddRef( (IUnknown*)*ppvObject );
96     return S_OK;
97 }
98
99 static ULONG WINAPI domelem_AddRef(
100     IXMLDOMElement *iface )
101 {
102     domelem *This = impl_from_IXMLDOMElement( iface );
103     LONG ref = InterlockedIncrement(&This->ref);
104
105     TRACE("(%p)->(%d)\n", This, ref);
106
107     return ref;
108 }
109
110 static ULONG WINAPI domelem_Release(
111     IXMLDOMElement *iface )
112 {
113     domelem *This = impl_from_IXMLDOMElement( iface );
114     ULONG ref = InterlockedDecrement(&This->ref);
115
116     TRACE("(%p)->(%d)\n", This, ref);
117
118     if(!ref) {
119         destroy_xmlnode(&This->node);
120         heap_free(This);
121     }
122
123     return ref;
124 }
125
126 static HRESULT WINAPI domelem_GetTypeInfoCount(
127     IXMLDOMElement *iface,
128     UINT* pctinfo )
129 {
130     domelem *This = impl_from_IXMLDOMElement( iface );
131
132     TRACE("(%p)->(%p)\n", This, pctinfo);
133
134     *pctinfo = 1;
135
136     return S_OK;
137 }
138
139 static HRESULT WINAPI domelem_GetTypeInfo(
140     IXMLDOMElement *iface,
141     UINT iTInfo, LCID lcid,
142     ITypeInfo** ppTInfo )
143 {
144     domelem *This = impl_from_IXMLDOMElement( iface );
145     HRESULT hr;
146
147     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
148
149     hr = get_typeinfo(IXMLDOMElement_tid, ppTInfo);
150
151     return hr;
152 }
153
154 static HRESULT WINAPI domelem_GetIDsOfNames(
155     IXMLDOMElement *iface,
156     REFIID riid, LPOLESTR* rgszNames,
157     UINT cNames, LCID lcid, DISPID* rgDispId )
158 {
159     domelem *This = impl_from_IXMLDOMElement( iface );
160     ITypeInfo *typeinfo;
161     HRESULT hr;
162
163     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
164           lcid, rgDispId);
165
166     if(!rgszNames || cNames == 0 || !rgDispId)
167         return E_INVALIDARG;
168
169     hr = get_typeinfo(IXMLDOMElement_tid, &typeinfo);
170     if(SUCCEEDED(hr))
171     {
172         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
173         ITypeInfo_Release(typeinfo);
174     }
175
176     return hr;
177 }
178
179 static HRESULT WINAPI domelem_Invoke(
180     IXMLDOMElement *iface,
181     DISPID dispIdMember, REFIID riid, LCID lcid,
182     WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
183     EXCEPINFO* pExcepInfo, UINT* puArgErr )
184 {
185     domelem *This = impl_from_IXMLDOMElement( iface );
186     ITypeInfo *typeinfo;
187     HRESULT hr;
188
189     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
190           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
191
192     hr = get_typeinfo(IXMLDOMElement_tid, &typeinfo);
193     if(SUCCEEDED(hr))
194     {
195         hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMElement_iface, dispIdMember, wFlags,
196                 pDispParams, pVarResult, pExcepInfo, puArgErr);
197         ITypeInfo_Release(typeinfo);
198     }
199
200     return hr;
201 }
202
203 static HRESULT WINAPI domelem_get_nodeName(
204     IXMLDOMElement *iface,
205     BSTR* p )
206 {
207     domelem *This = impl_from_IXMLDOMElement( iface );
208
209     TRACE("(%p)->(%p)\n", This, p);
210
211     return node_get_nodeName(&This->node, p);
212 }
213
214 static HRESULT WINAPI domelem_get_nodeValue(
215     IXMLDOMElement *iface,
216     VARIANT* value)
217 {
218     domelem *This = impl_from_IXMLDOMElement( iface );
219
220     TRACE("(%p)->(%p)\n", This, value);
221
222     if(!value)
223         return E_INVALIDARG;
224
225     V_VT(value) = VT_NULL;
226     V_BSTR(value) = NULL; /* tests show that we should do this */
227     return S_FALSE;
228 }
229
230 static HRESULT WINAPI domelem_put_nodeValue(
231     IXMLDOMElement *iface,
232     VARIANT value)
233 {
234     domelem *This = impl_from_IXMLDOMElement( iface );
235     TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
236     return E_FAIL;
237 }
238
239 static HRESULT WINAPI domelem_get_nodeType(
240     IXMLDOMElement *iface,
241     DOMNodeType* domNodeType )
242 {
243     domelem *This = impl_from_IXMLDOMElement( iface );
244
245     TRACE("(%p)->(%p)\n", This, domNodeType);
246
247     *domNodeType = NODE_ELEMENT;
248     return S_OK;
249 }
250
251 static HRESULT WINAPI domelem_get_parentNode(
252     IXMLDOMElement *iface,
253     IXMLDOMNode** parent )
254 {
255     domelem *This = impl_from_IXMLDOMElement( iface );
256
257     TRACE("(%p)->(%p)\n", This, parent);
258
259     return node_get_parent(&This->node, parent);
260 }
261
262 static HRESULT WINAPI domelem_get_childNodes(
263     IXMLDOMElement *iface,
264     IXMLDOMNodeList** outList)
265 {
266     domelem *This = impl_from_IXMLDOMElement( iface );
267
268     TRACE("(%p)->(%p)\n", This, outList);
269
270     return node_get_child_nodes(&This->node, outList);
271 }
272
273 static HRESULT WINAPI domelem_get_firstChild(
274     IXMLDOMElement *iface,
275     IXMLDOMNode** domNode)
276 {
277     domelem *This = impl_from_IXMLDOMElement( iface );
278
279     TRACE("(%p)->(%p)\n", This, domNode);
280
281     return node_get_first_child(&This->node, domNode);
282 }
283
284 static HRESULT WINAPI domelem_get_lastChild(
285     IXMLDOMElement *iface,
286     IXMLDOMNode** domNode)
287 {
288     domelem *This = impl_from_IXMLDOMElement( iface );
289
290     TRACE("(%p)->(%p)\n", This, domNode);
291
292     return node_get_last_child(&This->node, domNode);
293 }
294
295 static HRESULT WINAPI domelem_get_previousSibling(
296     IXMLDOMElement *iface,
297     IXMLDOMNode** domNode)
298 {
299     domelem *This = impl_from_IXMLDOMElement( iface );
300
301     TRACE("(%p)->(%p)\n", This, domNode);
302
303     return node_get_previous_sibling(&This->node, domNode);
304 }
305
306 static HRESULT WINAPI domelem_get_nextSibling(
307     IXMLDOMElement *iface,
308     IXMLDOMNode** domNode)
309 {
310     domelem *This = impl_from_IXMLDOMElement( iface );
311
312     TRACE("(%p)->(%p)\n", This, domNode);
313
314     return node_get_next_sibling(&This->node, domNode);
315 }
316
317 static HRESULT WINAPI domelem_get_attributes(
318     IXMLDOMElement *iface,
319     IXMLDOMNamedNodeMap** map)
320 {
321     domelem *This = impl_from_IXMLDOMElement( iface );
322
323     TRACE("(%p)->(%p)\n", This, map);
324
325     *map = create_nodemap(This->node.node, &domelem_attr_map);
326     return S_OK;
327 }
328
329 static HRESULT WINAPI domelem_insertBefore(
330     IXMLDOMElement *iface,
331     IXMLDOMNode* newNode, VARIANT refChild,
332     IXMLDOMNode** outOldNode)
333 {
334     domelem *This = impl_from_IXMLDOMElement( iface );
335
336     TRACE("(%p)->(%p %s %p)\n", This, newNode, debugstr_variant(&refChild), outOldNode);
337
338     return node_insert_before(&This->node, newNode, &refChild, outOldNode);
339 }
340
341 static HRESULT WINAPI domelem_replaceChild(
342     IXMLDOMElement *iface,
343     IXMLDOMNode* newNode,
344     IXMLDOMNode* oldNode,
345     IXMLDOMNode** outOldNode)
346 {
347     domelem *This = impl_from_IXMLDOMElement( iface );
348
349     TRACE("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
350
351     return node_replace_child(&This->node, newNode, oldNode, outOldNode);
352 }
353
354 static HRESULT WINAPI domelem_removeChild(
355     IXMLDOMElement *iface,
356     IXMLDOMNode *child, IXMLDOMNode **oldChild)
357 {
358     domelem *This = impl_from_IXMLDOMElement( iface );
359     TRACE("(%p)->(%p %p)\n", This, child, oldChild);
360     return node_remove_child(&This->node, child, oldChild);
361 }
362
363 static HRESULT WINAPI domelem_appendChild(
364     IXMLDOMElement *iface,
365     IXMLDOMNode *child, IXMLDOMNode **outChild)
366 {
367     domelem *This = impl_from_IXMLDOMElement( iface );
368     TRACE("(%p)->(%p %p)\n", This, child, outChild);
369     return node_append_child(&This->node, child, outChild);
370 }
371
372 static HRESULT WINAPI domelem_hasChildNodes(
373     IXMLDOMElement *iface,
374     VARIANT_BOOL *ret)
375 {
376     domelem *This = impl_from_IXMLDOMElement( iface );
377     TRACE("(%p)->(%p)\n", This, ret);
378     return node_has_childnodes(&This->node, ret);
379 }
380
381 static HRESULT WINAPI domelem_get_ownerDocument(
382     IXMLDOMElement   *iface,
383     IXMLDOMDocument **doc)
384 {
385     domelem *This = impl_from_IXMLDOMElement( iface );
386     TRACE("(%p)->(%p)\n", This, doc);
387     return node_get_owner_doc(&This->node, doc);
388 }
389
390 static HRESULT WINAPI domelem_cloneNode(
391     IXMLDOMElement *iface,
392     VARIANT_BOOL deep, IXMLDOMNode** outNode)
393 {
394     domelem *This = impl_from_IXMLDOMElement( iface );
395     TRACE("(%p)->(%d %p)\n", This, deep, outNode);
396     return node_clone( &This->node, deep, outNode );
397 }
398
399 static HRESULT WINAPI domelem_get_nodeTypeString(
400     IXMLDOMElement *iface,
401     BSTR* p)
402 {
403     domelem *This = impl_from_IXMLDOMElement( iface );
404     static const WCHAR elementW[] = {'e','l','e','m','e','n','t',0};
405
406     TRACE("(%p)->(%p)\n", This, p);
407
408     return return_bstr(elementW, p);
409 }
410
411 static HRESULT WINAPI domelem_get_text(
412     IXMLDOMElement *iface,
413     BSTR* p)
414 {
415     domelem *This = impl_from_IXMLDOMElement( iface );
416     TRACE("(%p)->(%p)\n", This, p);
417     return node_get_text(&This->node, p);
418 }
419
420 static HRESULT WINAPI domelem_put_text(
421     IXMLDOMElement *iface,
422     BSTR p)
423 {
424     domelem *This = impl_from_IXMLDOMElement( iface );
425     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
426     return node_put_text( &This->node, p );
427 }
428
429 static HRESULT WINAPI domelem_get_specified(
430     IXMLDOMElement *iface,
431     VARIANT_BOOL* isSpecified)
432 {
433     domelem *This = impl_from_IXMLDOMElement( iface );
434     FIXME("(%p)->(%p) stub!\n", This, isSpecified);
435     *isSpecified = VARIANT_TRUE;
436     return S_OK;
437 }
438
439 static HRESULT WINAPI domelem_get_definition(
440     IXMLDOMElement *iface,
441     IXMLDOMNode** definitionNode)
442 {
443     domelem *This = impl_from_IXMLDOMElement( iface );
444     FIXME("(%p)->(%p)\n", This, definitionNode);
445     return E_NOTIMPL;
446 }
447
448 static inline BYTE hex_to_byte(xmlChar c)
449 {
450     if(c <= '9') return c-'0';
451     if(c <= 'F') return c-'A'+10;
452     return c-'a'+10;
453 }
454
455 static inline BYTE base64_to_byte(xmlChar c)
456 {
457     if(c == '+') return 62;
458     if(c == '/') return 63;
459     if(c <= '9') return c-'0'+52;
460     if(c <= 'Z') return c-'A';
461     return c-'a'+26;
462 }
463
464 static inline HRESULT variant_from_dt(XDR_DT dt, xmlChar* str, VARIANT* v)
465 {
466     VARIANT src;
467     HRESULT hr = S_OK;
468     BOOL handled = FALSE;
469
470     VariantInit(&src);
471
472     switch (dt)
473     {
474     case DT_INVALID:
475     case DT_STRING:
476     case DT_NMTOKEN:
477     case DT_NMTOKENS:
478     case DT_NUMBER:
479     case DT_URI:
480     case DT_UUID:
481         {
482             V_VT(v) = VT_BSTR;
483             V_BSTR(v) = bstr_from_xmlChar(str);
484
485             if(!V_BSTR(v))
486                 return E_OUTOFMEMORY;
487             handled = TRUE;
488         }
489         break;
490     case DT_DATE:
491     case DT_DATE_TZ:
492     case DT_DATETIME:
493     case DT_DATETIME_TZ:
494     case DT_TIME:
495     case DT_TIME_TZ:
496         {
497             WCHAR *p, *e;
498             SYSTEMTIME st;
499             DOUBLE date = 0.0;
500
501             st.wYear = 1899;
502             st.wMonth = 12;
503             st.wDay = 30;
504             st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
505
506             V_VT(&src) = VT_BSTR;
507             V_BSTR(&src) = bstr_from_xmlChar(str);
508
509             if(!V_BSTR(&src))
510                 return E_OUTOFMEMORY;
511
512             p = V_BSTR(&src);
513             e = p + SysStringLen(V_BSTR(&src));
514
515             if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
516             {
517                 st.wYear = atoiW(p);
518                 st.wMonth = atoiW(p+5);
519                 st.wDay = atoiW(p+8);
520                 p += 10;
521
522                 if(*p == 'T') p++;
523             }
524
525             if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
526             {
527                 st.wHour = atoiW(p);
528                 st.wMinute = atoiW(p+3);
529                 st.wSecond = atoiW(p+6);
530                 p += 8;
531
532                 if(*p == '.')
533                 {
534                     p++;
535                     while(isdigitW(*p)) p++;
536                 }
537             }
538
539             SystemTimeToVariantTime(&st, &date);
540             V_VT(v) = VT_DATE;
541             V_DATE(v) = date;
542
543             if(*p == '+') /* parse timezone offset (+hh:mm) */
544                 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
545             else if(*p == '-') /* parse timezone offset (-hh:mm) */
546                 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
547
548             VariantClear(&src);
549             handled = TRUE;
550         }
551         break;
552     case DT_BIN_HEX:
553         {
554             SAFEARRAYBOUND sab;
555             int i, len;
556
557             len = xmlStrlen(str)/2;
558             sab.lLbound = 0;
559             sab.cElements = len;
560
561             V_VT(v) = (VT_ARRAY|VT_UI1);
562             V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
563
564             if(!V_ARRAY(v))
565                 return E_OUTOFMEMORY;
566
567             for(i=0; i<len; i++)
568                 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
569                     + hex_to_byte(str[2*i+1]);
570             handled = TRUE;
571         }
572         break;
573     case DT_BIN_BASE64:
574         {
575             SAFEARRAYBOUND sab;
576             xmlChar *c1, *c2;
577             int i, len;
578
579             /* remove all formatting chars */
580             c1 = c2 = str;
581             len = 0;
582             while (*c2)
583             {
584                 if ( *c2 == ' '  || *c2 == '\t' ||
585                      *c2 == '\n' || *c2 == '\r' )
586                 {
587                     c2++;
588                     continue;
589                 }
590                 *c1++ = *c2++;
591                 len++;
592             }
593
594             /* skip padding */
595             if(str[len-2] == '=') i = 2;
596             else if(str[len-1] == '=') i = 1;
597             else i = 0;
598
599             sab.lLbound = 0;
600             sab.cElements = len/4*3-i;
601
602             V_VT(v) = (VT_ARRAY|VT_UI1);
603             V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
604
605             if(!V_ARRAY(v))
606                 return E_OUTOFMEMORY;
607
608             for(i=0; i<len/4; i++)
609             {
610                 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
611                     + (base64_to_byte(str[4*i+1])>>4);
612                 if(3*i+1 < sab.cElements)
613                     ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
614                         + (base64_to_byte(str[4*i+2])>>2);
615                 if(3*i+2 < sab.cElements)
616                     ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
617                         + base64_to_byte(str[4*i+3]);
618             }
619             handled = TRUE;
620         }
621         break;
622     case DT_BOOLEAN:
623         V_VT(v) = VT_BOOL;
624         break;
625     case DT_FIXED_14_4:
626         V_VT(v) = VT_CY;
627         break;
628     case DT_I1:
629         V_VT(v) = VT_I1;
630         break;
631     case DT_I2:
632         V_VT(v) = VT_I2;
633         break;
634     case DT_I4:
635     case DT_INT:
636         V_VT(v) = VT_I4;
637         break;
638     case DT_I8:
639         V_VT(v) = VT_I8;
640         break;
641     case DT_R4:
642         V_VT(v) = VT_R4;
643         break;
644     case DT_FLOAT:
645     case DT_R8:
646         V_VT(v) = VT_R8;
647         break;
648     case DT_UI1:
649         V_VT(v) = VT_UI1;
650         break;
651     case DT_UI2:
652         V_VT(v) = VT_UI2;
653         break;
654     case DT_UI4:
655         V_VT(v) = VT_UI4;
656         break;
657     case DT_UI8:
658         V_VT(v) = VT_UI8;
659         break;
660     case DT_CHAR:
661     case DT_ENTITY:
662     case DT_ENTITIES:
663     case DT_ENUMERATION:
664     case DT_ID:
665     case DT_IDREF:
666     case DT_IDREFS:
667     case DT_NOTATION:
668         FIXME("need to handle dt:%s\n", debugstr_dt(dt));
669         V_VT(v) = VT_BSTR;
670         V_BSTR(v) = bstr_from_xmlChar(str);
671         if (!V_BSTR(v))
672             return E_OUTOFMEMORY;
673         handled = TRUE;
674         break;
675     }
676
677     if (!handled)
678     {
679         V_VT(&src) = VT_BSTR;
680         V_BSTR(&src) = bstr_from_xmlChar(str);
681
682         if(!V_BSTR(&src))
683             return E_OUTOFMEMORY;
684
685         hr = VariantChangeTypeEx(v, &src,
686                 MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
687         VariantClear(&src);
688     }
689     return hr;
690 }
691
692 static XDR_DT element_get_dt(xmlNodePtr node)
693 {
694     XDR_DT dt = DT_INVALID;
695
696     TRACE("(%p)\n", node);
697     if(node->type != XML_ELEMENT_NODE)
698     {
699         FIXME("invalid element node\n");
700         return dt;
701     }
702
703     if (node->ns && xmlStrEqual(node->ns->href, DT_nsURI))
704     {
705         dt = str_to_dt(node->name, -1);
706     }
707     else
708     {
709         xmlChar* pVal = xmlGetNsProp(node, BAD_CAST "dt", DT_nsURI);
710         if (pVal)
711         {
712             dt = str_to_dt(pVal, -1);
713             xmlFree(pVal);
714         }
715         else if (node->doc)
716         {
717             IXMLDOMDocument3* doc = (IXMLDOMDocument3*)create_domdoc((xmlNodePtr)node->doc);
718             if (doc)
719             {
720                 VARIANT v;
721                 VariantInit(&v);
722
723                 if (IXMLDOMDocument3_get_schemas(doc, &v) == S_OK &&
724                     V_VT(&v) == VT_DISPATCH)
725                 {
726                     dt = SchemaCache_get_node_dt((IXMLDOMSchemaCollection2*)V_DISPATCH(&v), node);
727                 }
728                 VariantClear(&v);
729                 IXMLDOMDocument3_Release(doc);
730             }
731         }
732     }
733
734     TRACE("=> dt:%s\n", debugstr_dt(dt));
735     return dt;
736 }
737
738 static HRESULT WINAPI domelem_get_nodeTypedValue(
739     IXMLDOMElement *iface,
740     VARIANT* v)
741 {
742     domelem *This = impl_from_IXMLDOMElement( iface );
743     XDR_DT dt;
744     xmlChar* content;
745     HRESULT hr;
746
747     TRACE("(%p)->(%p)\n", This, v);
748
749     if(!v) return E_INVALIDARG;
750
751     V_VT(v) = VT_NULL;
752
753     dt = element_get_dt(get_element(This));
754     content = xmlNodeGetContent(get_element(This));
755     hr = variant_from_dt(dt, content, v);
756     xmlFree(content);
757
758     return hr;
759 }
760
761 static HRESULT WINAPI domelem_put_nodeTypedValue(
762     IXMLDOMElement *iface,
763     VARIANT value)
764 {
765     domelem *This = impl_from_IXMLDOMElement( iface );
766     XDR_DT dt;
767     HRESULT hr;
768
769     TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
770
771     dt = element_get_dt(get_element(This));
772     /* for untyped node coerce to BSTR and set */
773     if (dt == DT_INVALID)
774     {
775         if (V_VT(&value) != VT_BSTR)
776         {
777             VARIANT content;
778             VariantInit(&content);
779             hr = VariantChangeType(&content, &value, 0, VT_BSTR);
780             if (hr == S_OK)
781             {
782                 hr = node_set_content(&This->node, V_BSTR(&content));
783                 VariantClear(&content);
784             }
785         }
786         else
787             hr = node_set_content(&This->node, V_BSTR(&value));
788     }
789     else
790     {
791         FIXME("not implemented for dt:%s\n", debugstr_dt(dt));
792         return E_NOTIMPL;
793     }
794
795     return hr;
796 }
797
798 static HRESULT WINAPI domelem_get_dataType(
799     IXMLDOMElement *iface,
800     VARIANT* typename)
801 {
802     domelem *This = impl_from_IXMLDOMElement( iface );
803     XDR_DT dt;
804
805     TRACE("(%p)->(%p)\n", This, typename);
806
807     if (!typename)
808         return E_INVALIDARG;
809
810     dt = element_get_dt(get_element(This));
811     switch (dt)
812     {
813         case DT_BIN_BASE64:
814         case DT_BIN_HEX:
815         case DT_BOOLEAN:
816         case DT_CHAR:
817         case DT_DATE:
818         case DT_DATE_TZ:
819         case DT_DATETIME:
820         case DT_DATETIME_TZ:
821         case DT_FIXED_14_4:
822         case DT_FLOAT:
823         case DT_I1:
824         case DT_I2:
825         case DT_I4:
826         case DT_I8:
827         case DT_INT:
828         case DT_NUMBER:
829         case DT_R4:
830         case DT_R8:
831         case DT_TIME:
832         case DT_TIME_TZ:
833         case DT_UI1:
834         case DT_UI2:
835         case DT_UI4:
836         case DT_UI8:
837         case DT_URI:
838         case DT_UUID:
839             V_VT(typename) = VT_BSTR;
840             V_BSTR(typename) = SysAllocString(dt_to_bstr(dt));
841
842             if (!V_BSTR(typename))
843                 return E_OUTOFMEMORY;
844             break;
845         default:
846             /* Other types (DTD equivalents) do not return anything here,
847              * but the pointer part of the VARIANT is set to NULL */
848             V_VT(typename) = VT_NULL;
849             V_BSTR(typename) = NULL;
850             break;
851     }
852     return (V_VT(typename) != VT_NULL) ? S_OK : S_FALSE;
853 }
854
855 static HRESULT WINAPI domelem_put_dataType(
856     IXMLDOMElement *iface,
857     BSTR dtName)
858 {
859     domelem *This = impl_from_IXMLDOMElement( iface );
860     HRESULT hr = E_FAIL;
861     xmlChar *str;
862     XDR_DT dt;
863
864     TRACE("(%p)->(%s)\n", This, debugstr_w(dtName));
865
866     if(dtName == NULL)
867         return E_INVALIDARG;
868
869     dt = bstr_to_dt(dtName, -1);
870
871     /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
872        This applies to changing types (string->bool) or setting a new one
873      */
874     str = xmlNodeGetContent(get_element(This));
875     hr = dt_validate(dt, str);
876     xmlFree(str);
877
878     /* Check all supported types. */
879     if (hr == S_OK)
880     {
881         switch (dt)
882         {
883         case DT_BIN_BASE64:
884         case DT_BIN_HEX:
885         case DT_BOOLEAN:
886         case DT_CHAR:
887         case DT_DATE:
888         case DT_DATE_TZ:
889         case DT_DATETIME:
890         case DT_DATETIME_TZ:
891         case DT_FIXED_14_4:
892         case DT_FLOAT:
893         case DT_I1:
894         case DT_I2:
895         case DT_I4:
896         case DT_I8:
897         case DT_INT:
898         case DT_NMTOKEN:
899         case DT_NMTOKENS:
900         case DT_NUMBER:
901         case DT_R4:
902         case DT_R8:
903         case DT_STRING:
904         case DT_TIME:
905         case DT_TIME_TZ:
906         case DT_UI1:
907         case DT_UI2:
908         case DT_UI4:
909         case DT_UI8:
910         case DT_URI:
911         case DT_UUID:
912             {
913                 xmlAttrPtr attr = xmlHasNsProp(get_element(This), DT_prefix, DT_nsURI);
914                 if (attr)
915                 {
916                     attr = xmlSetNsProp(get_element(This), attr->ns, DT_prefix, dt_to_str(dt));
917                     hr = S_OK;
918                 }
919                 else
920                 {
921                     xmlNsPtr ns = xmlNewNs(get_element(This), DT_nsURI, DT_prefix);
922                     if (ns)
923                     {
924                         attr = xmlNewNsProp(get_element(This), ns, DT_prefix, dt_to_str(dt));
925                         if (attr)
926                         {
927                             xmlAddChild(get_element(This), (xmlNodePtr)attr);
928                             hr = S_OK;
929                         }
930                         else
931                             ERR("Failed to create Attribute\n");
932                     }
933                     else
934                         ERR("Failed to create Namespace\n");
935                 }
936             }
937             break;
938         default:
939             FIXME("need to handle dt:%s\n", debugstr_dt(dt));
940             break;
941         }
942     }
943
944     return hr;
945 }
946
947 static HRESULT WINAPI domelem_get_xml(
948     IXMLDOMElement *iface,
949     BSTR* p)
950 {
951     domelem *This = impl_from_IXMLDOMElement( iface );
952
953     TRACE("(%p)->(%p)\n", This, p);
954
955     return node_get_xml(&This->node, TRUE, FALSE, p);
956 }
957
958 static HRESULT WINAPI domelem_transformNode(
959     IXMLDOMElement *iface,
960     IXMLDOMNode *node, BSTR *p)
961 {
962     domelem *This = impl_from_IXMLDOMElement( iface );
963     TRACE("(%p)->(%p %p)\n", This, node, p);
964     return node_transform_node(&This->node, node, p);
965 }
966
967 static HRESULT WINAPI domelem_selectNodes(
968     IXMLDOMElement *iface,
969     BSTR p, IXMLDOMNodeList** outList)
970 {
971     domelem *This = impl_from_IXMLDOMElement( iface );
972     TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
973     return node_select_nodes(&This->node, p, outList);
974 }
975
976 static HRESULT WINAPI domelem_selectSingleNode(
977     IXMLDOMElement *iface,
978     BSTR p, IXMLDOMNode** outNode)
979 {
980     domelem *This = impl_from_IXMLDOMElement( iface );
981     TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
982     return node_select_singlenode(&This->node, p, outNode);
983 }
984
985 static HRESULT WINAPI domelem_get_parsed(
986     IXMLDOMElement *iface,
987     VARIANT_BOOL* isParsed)
988 {
989     domelem *This = impl_from_IXMLDOMElement( iface );
990     FIXME("(%p)->(%p) stub!\n", This, isParsed);
991     *isParsed = VARIANT_TRUE;
992     return S_OK;
993 }
994
995 static HRESULT WINAPI domelem_get_namespaceURI(
996     IXMLDOMElement *iface,
997     BSTR* p)
998 {
999     domelem *This = impl_from_IXMLDOMElement( iface );
1000     TRACE("(%p)->(%p)\n", This, p);
1001     return node_get_namespaceURI(&This->node, p);
1002 }
1003
1004 static HRESULT WINAPI domelem_get_prefix(
1005     IXMLDOMElement *iface,
1006     BSTR* prefix)
1007 {
1008     domelem *This = impl_from_IXMLDOMElement( iface );
1009     TRACE("(%p)->(%p)\n", This, prefix);
1010     return node_get_prefix( &This->node, prefix );
1011 }
1012
1013 static HRESULT WINAPI domelem_get_baseName(
1014     IXMLDOMElement *iface,
1015     BSTR* name)
1016 {
1017     domelem *This = impl_from_IXMLDOMElement( iface );
1018     TRACE("(%p)->(%p)\n", This, name);
1019     return node_get_base_name( &This->node, name );
1020 }
1021
1022 static HRESULT WINAPI domelem_transformNodeToObject(
1023     IXMLDOMElement *iface,
1024     IXMLDOMNode* domNode, VARIANT var1)
1025 {
1026     domelem *This = impl_from_IXMLDOMElement( iface );
1027     FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1028     return E_NOTIMPL;
1029 }
1030
1031 static HRESULT WINAPI domelem_get_tagName(
1032     IXMLDOMElement *iface,
1033     BSTR* p)
1034 {
1035     domelem *This = impl_from_IXMLDOMElement( iface );
1036     xmlNodePtr element;
1037     const xmlChar *prefix;
1038     xmlChar *qname;
1039
1040     TRACE("(%p)->(%p)\n", This, p );
1041
1042     if (!p) return E_INVALIDARG;
1043
1044     element = get_element( This );
1045     if ( !element )
1046         return E_FAIL;
1047
1048     prefix = element->ns ? element->ns->prefix : NULL;
1049     qname = xmlBuildQName(element->name, prefix, NULL, 0);
1050
1051     *p = bstr_from_xmlChar(qname);
1052     if (qname != element->name) xmlFree(qname);
1053
1054     return *p ? S_OK : E_OUTOFMEMORY;
1055 }
1056
1057 static HRESULT WINAPI domelem_getAttribute(
1058     IXMLDOMElement *iface,
1059     BSTR name, VARIANT* value)
1060 {
1061     domelem *This = impl_from_IXMLDOMElement( iface );
1062     xmlNodePtr element;
1063     xmlChar *xml_name, *xml_value = NULL;
1064     HRESULT hr = S_FALSE;
1065
1066     TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), value);
1067
1068     if(!value || !name)
1069         return E_INVALIDARG;
1070
1071     element = get_element( This );
1072     if ( !element )
1073         return E_FAIL;
1074
1075     V_BSTR(value) = NULL;
1076     V_VT(value) = VT_NULL;
1077
1078     xml_name = xmlchar_from_wchar( name );
1079
1080     if(!xmlValidateNameValue(xml_name))
1081         hr = E_FAIL;
1082     else
1083         xml_value = xmlGetNsProp(element, xml_name, NULL);
1084
1085     heap_free(xml_name);
1086     if(xml_value)
1087     {
1088         V_VT(value) = VT_BSTR;
1089         V_BSTR(value) = bstr_from_xmlChar( xml_value );
1090         xmlFree(xml_value);
1091         hr = S_OK;
1092     }
1093
1094     return hr;
1095 }
1096
1097 static HRESULT WINAPI domelem_setAttribute(
1098     IXMLDOMElement *iface,
1099     BSTR name, VARIANT value)
1100 {
1101     domelem *This = impl_from_IXMLDOMElement( iface );
1102     xmlChar *xml_name, *xml_value, *local, *prefix;
1103     xmlNodePtr element;
1104     HRESULT hr;
1105     VARIANT var;
1106
1107     TRACE("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_variant(&value));
1108
1109     element = get_element( This );
1110     if ( !element )
1111         return E_FAIL;
1112
1113     VariantInit(&var);
1114     hr = VariantChangeType(&var, &value, 0, VT_BSTR);
1115     if(hr != S_OK)
1116     {
1117         FIXME("VariantChangeType failed\n");
1118         return hr;
1119     }
1120
1121     xml_name = xmlchar_from_wchar( name );
1122     xml_value = xmlchar_from_wchar( V_BSTR(&var) );
1123
1124     if ((local = xmlSplitQName2(xml_name, &prefix)))
1125     {
1126         static const xmlChar* xmlnsA = (const xmlChar*)"xmlns";
1127         xmlNsPtr ns = NULL;
1128
1129         /* it's not allowed to modify existing namespace definition */
1130         if (xmlStrEqual(prefix, xmlnsA))
1131             ns = xmlSearchNs(element->doc, element, local);
1132
1133         xmlFree(prefix);
1134         xmlFree(local);
1135
1136         if (ns)
1137             return xmlStrEqual(ns->href, xml_value) ? S_OK : E_INVALIDARG;
1138     }
1139
1140     if (!xmlSetNsProp(element, NULL, xml_name, xml_value))
1141         hr = E_FAIL;
1142
1143     heap_free(xml_value);
1144     heap_free(xml_name);
1145     VariantClear(&var);
1146
1147     return hr;
1148 }
1149
1150 static HRESULT WINAPI domelem_removeAttribute(
1151     IXMLDOMElement *iface,
1152     BSTR p)
1153 {
1154     domelem *This = impl_from_IXMLDOMElement( iface );
1155     IXMLDOMNamedNodeMap *attr;
1156     HRESULT hr;
1157
1158     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1159
1160     hr = IXMLDOMElement_get_attributes(iface, &attr);
1161     if (hr != S_OK) return hr;
1162
1163     hr = IXMLDOMNamedNodeMap_removeNamedItem(attr, p, NULL);
1164     IXMLDOMNamedNodeMap_Release(attr);
1165
1166     return hr;
1167 }
1168
1169 static HRESULT WINAPI domelem_getAttributeNode(
1170     IXMLDOMElement *iface,
1171     BSTR p, IXMLDOMAttribute** attributeNode )
1172 {
1173     domelem *This = impl_from_IXMLDOMElement( iface );
1174     xmlChar *local, *prefix, *nameA;
1175     HRESULT hr = S_FALSE;
1176     xmlNodePtr element;
1177     xmlAttrPtr attr;
1178
1179     TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), attributeNode);
1180
1181     element = get_element( This );
1182     if (!element) return E_FAIL;
1183
1184     if (attributeNode) *attributeNode = NULL;
1185
1186     nameA = xmlchar_from_wchar(p);
1187     if (!xmlValidateNameValue(nameA))
1188     {
1189         heap_free(nameA);
1190         return E_FAIL;
1191     }
1192
1193     if (!attributeNode)
1194     {
1195         heap_free(nameA);
1196         return S_FALSE;
1197     }
1198
1199     *attributeNode = NULL;
1200
1201     local = xmlSplitQName2(nameA, &prefix);
1202
1203     if (local)
1204     {
1205         /* try to get namespace for supplied qualified name */
1206         xmlNsPtr ns = xmlSearchNs(element->doc, element, prefix);
1207         xmlFree(prefix);
1208
1209         attr = xmlHasNsProp(element, local, ns ? ns->href : NULL);
1210         xmlFree(local);
1211     }
1212     else
1213     {
1214         attr = xmlHasProp(element, nameA);
1215         /* attribute has attached namespace and we requested non-qualified
1216            name - it's a failure case */
1217         if (attr && attr->ns) attr = NULL;
1218     }
1219
1220     heap_free(nameA);
1221
1222     if (attr)
1223     {
1224         IUnknown *unk = create_attribute((xmlNodePtr)attr);
1225         hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMAttribute, (void**)attributeNode);
1226         IUnknown_Release(unk);
1227     }
1228
1229     return hr;
1230 }
1231
1232 static HRESULT WINAPI domelem_setAttributeNode(
1233     IXMLDOMElement *iface,
1234     IXMLDOMAttribute* attribute,
1235     IXMLDOMAttribute** old)
1236 {
1237     domelem *This = impl_from_IXMLDOMElement( iface );
1238     static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
1239     xmlChar *name, *value;
1240     BSTR nameW, prefix;
1241     xmlnode *attr_node;
1242     xmlAttrPtr attr;
1243     VARIANT valueW;
1244     HRESULT hr;
1245
1246     FIXME("(%p)->(%p %p): semi-stub\n", This, attribute, old);
1247
1248     if (!attribute) return E_INVALIDARG;
1249
1250     attr_node = get_node_obj((IXMLDOMNode*)attribute);
1251     if (!attr_node) return E_FAIL;
1252
1253     if (attr_node->parent)
1254     {
1255         WARN("attempt to add already used attribute\n");
1256         return E_FAIL;
1257     }
1258
1259     hr = IXMLDOMAttribute_get_nodeName(attribute, &nameW);
1260     if (hr != S_OK) return hr;
1261
1262     /* adding xmlns attribute doesn't change a tree or existing namespace definition */
1263     if (!strcmpW(nameW, xmlnsW))
1264     {
1265         SysFreeString(nameW);
1266         return DISP_E_UNKNOWNNAME;
1267     }
1268
1269     hr = IXMLDOMAttribute_get_nodeValue(attribute, &valueW);
1270     if (hr != S_OK)
1271     {
1272         SysFreeString(nameW);
1273         return hr;
1274     }
1275
1276     if (old) *old = NULL;
1277
1278     TRACE("attribute: %s=%s\n", debugstr_w(nameW), debugstr_w(V_BSTR(&valueW)));
1279
1280     hr = IXMLDOMAttribute_get_prefix(attribute, &prefix);
1281     if (hr == S_OK)
1282     {
1283         FIXME("namespaces not supported: %s\n", debugstr_w(prefix));
1284         SysFreeString(prefix);
1285     }
1286
1287     name = xmlchar_from_wchar(nameW);
1288     value = xmlchar_from_wchar(V_BSTR(&valueW));
1289
1290     if (!name || !value)
1291     {
1292         SysFreeString(nameW);
1293         VariantClear(&valueW);
1294         heap_free(name);
1295         heap_free(value);
1296         return E_OUTOFMEMORY;
1297     }
1298
1299     attr = xmlSetNsProp(get_element(This), NULL, name, value);
1300     if (attr)
1301         attr_node->parent = (IXMLDOMNode*)iface;
1302
1303     SysFreeString(nameW);
1304     VariantClear(&valueW);
1305     heap_free(name);
1306     heap_free(value);
1307
1308     return attr ? S_OK : E_FAIL;
1309 }
1310
1311 static HRESULT WINAPI domelem_removeAttributeNode(
1312     IXMLDOMElement *iface,
1313     IXMLDOMAttribute* domAttribute,
1314     IXMLDOMAttribute** attributeNode)
1315 {
1316     domelem *This = impl_from_IXMLDOMElement( iface );
1317     FIXME("(%p)->(%p %p)\n", This, domAttribute, attributeNode);
1318     return E_NOTIMPL;
1319 }
1320
1321 static HRESULT WINAPI domelem_getElementsByTagName(
1322     IXMLDOMElement *iface,
1323     BSTR tagName, IXMLDOMNodeList** resultList)
1324 {
1325     domelem *This = impl_from_IXMLDOMElement( iface );
1326     xmlChar *query;
1327     HRESULT hr;
1328     BOOL XPath;
1329
1330     TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1331
1332     if (!tagName || !resultList) return E_INVALIDARG;
1333
1334     XPath = is_xpathmode(get_element(This)->doc);
1335     set_xpathmode(get_element(This)->doc, TRUE);
1336     query = tagName_to_XPath(tagName);
1337     hr = create_selection(get_element(This), query, resultList);
1338     xmlFree(query);
1339     set_xpathmode(get_element(This)->doc, XPath);
1340
1341     return hr;
1342 }
1343
1344 static HRESULT WINAPI domelem_normalize(
1345     IXMLDOMElement *iface )
1346 {
1347     domelem *This = impl_from_IXMLDOMElement( iface );
1348     FIXME("%p\n", This);
1349     return E_NOTIMPL;
1350 }
1351
1352 static const struct IXMLDOMElementVtbl domelem_vtbl =
1353 {
1354     domelem_QueryInterface,
1355     domelem_AddRef,
1356     domelem_Release,
1357     domelem_GetTypeInfoCount,
1358     domelem_GetTypeInfo,
1359     domelem_GetIDsOfNames,
1360     domelem_Invoke,
1361     domelem_get_nodeName,
1362     domelem_get_nodeValue,
1363     domelem_put_nodeValue,
1364     domelem_get_nodeType,
1365     domelem_get_parentNode,
1366     domelem_get_childNodes,
1367     domelem_get_firstChild,
1368     domelem_get_lastChild,
1369     domelem_get_previousSibling,
1370     domelem_get_nextSibling,
1371     domelem_get_attributes,
1372     domelem_insertBefore,
1373     domelem_replaceChild,
1374     domelem_removeChild,
1375     domelem_appendChild,
1376     domelem_hasChildNodes,
1377     domelem_get_ownerDocument,
1378     domelem_cloneNode,
1379     domelem_get_nodeTypeString,
1380     domelem_get_text,
1381     domelem_put_text,
1382     domelem_get_specified,
1383     domelem_get_definition,
1384     domelem_get_nodeTypedValue,
1385     domelem_put_nodeTypedValue,
1386     domelem_get_dataType,
1387     domelem_put_dataType,
1388     domelem_get_xml,
1389     domelem_transformNode,
1390     domelem_selectNodes,
1391     domelem_selectSingleNode,
1392     domelem_get_parsed,
1393     domelem_get_namespaceURI,
1394     domelem_get_prefix,
1395     domelem_get_baseName,
1396     domelem_transformNodeToObject,
1397     domelem_get_tagName,
1398     domelem_getAttribute,
1399     domelem_setAttribute,
1400     domelem_removeAttribute,
1401     domelem_getAttributeNode,
1402     domelem_setAttributeNode,
1403     domelem_removeAttributeNode,
1404     domelem_getElementsByTagName,
1405     domelem_normalize,
1406 };
1407
1408 static HRESULT domelem_get_qualified_item(const xmlNodePtr node, BSTR name, BSTR uri,
1409     IXMLDOMNode **item)
1410 {
1411     xmlAttrPtr attr;
1412     xmlChar *nameA;
1413     xmlChar *href;
1414
1415     TRACE("(%p)->(%s %s %p)\n", node, debugstr_w(name), debugstr_w(uri), item);
1416
1417     if (!name || !item) return E_INVALIDARG;
1418
1419     if (uri && *uri)
1420     {
1421         href = xmlchar_from_wchar(uri);
1422         if (!href) return E_OUTOFMEMORY;
1423     }
1424     else
1425         href = NULL;
1426
1427     nameA = xmlchar_from_wchar(name);
1428     if (!nameA)
1429     {
1430         heap_free(href);
1431         return E_OUTOFMEMORY;
1432     }
1433
1434     attr = xmlHasNsProp(node, nameA, href);
1435
1436     heap_free(nameA);
1437     heap_free(href);
1438
1439     if (!attr)
1440     {
1441         *item = NULL;
1442         return S_FALSE;
1443     }
1444
1445     *item = create_node((xmlNodePtr)attr);
1446
1447     return S_OK;
1448 }
1449
1450 static HRESULT domelem_get_named_item(const xmlNodePtr node, BSTR name, IXMLDOMNode **item)
1451 {
1452     xmlChar *nameA, *local, *prefix;
1453     BSTR uriW, localW;
1454     xmlNsPtr ns;
1455     HRESULT hr;
1456
1457     TRACE("(%p)->(%s %p)\n", node, debugstr_w(name), item );
1458
1459     nameA = xmlchar_from_wchar(name);
1460     local = xmlSplitQName2(nameA, &prefix);
1461     heap_free(nameA);
1462
1463     if (!local)
1464         return domelem_get_qualified_item(node, name, NULL, item);
1465
1466     /* try to get namespace uri for supplied qualified name */
1467     ns = xmlSearchNs(node->doc, node, prefix);
1468
1469     xmlFree(prefix);
1470
1471     if (!ns)
1472     {
1473         xmlFree(local);
1474         if (item) *item = NULL;
1475         return item ? S_FALSE : E_INVALIDARG;
1476     }
1477
1478     uriW = bstr_from_xmlChar(ns->href);
1479     localW = bstr_from_xmlChar(local);
1480     xmlFree(local);
1481
1482     TRACE("got qualified node %s, uri=%s\n", debugstr_w(localW), debugstr_w(uriW));
1483
1484     hr = domelem_get_qualified_item(node, localW, uriW, item);
1485
1486     SysFreeString(localW);
1487     SysFreeString(uriW);
1488
1489     return hr;
1490 }
1491
1492 static HRESULT domelem_set_named_item(xmlNodePtr node, IXMLDOMNode *newItem, IXMLDOMNode **namedItem)
1493 {
1494     xmlNodePtr nodeNew;
1495     xmlnode *ThisNew;
1496
1497     TRACE("(%p)->(%p %p)\n", node, newItem, namedItem );
1498
1499     if(!newItem)
1500         return E_INVALIDARG;
1501
1502     if(namedItem) *namedItem = NULL;
1503
1504     /* Must be an Attribute */
1505     ThisNew = get_node_obj( newItem );
1506     if(!ThisNew) return E_FAIL;
1507
1508     if(ThisNew->node->type != XML_ATTRIBUTE_NODE)
1509         return E_FAIL;
1510
1511     if(!ThisNew->node->parent)
1512         if(xmldoc_remove_orphan(ThisNew->node->doc, ThisNew->node) != S_OK)
1513             WARN("%p is not an orphan of %p\n", ThisNew->node, ThisNew->node->doc);
1514
1515     nodeNew = xmlAddChild(node, ThisNew->node);
1516
1517     if(namedItem)
1518         *namedItem = create_node( nodeNew );
1519     return S_OK;
1520 }
1521
1522 static HRESULT domelem_remove_qualified_item(xmlNodePtr node, BSTR name, BSTR uri, IXMLDOMNode **item)
1523 {
1524     xmlChar *nameA, *href;
1525     xmlAttrPtr attr;
1526
1527     TRACE("(%p)->(%s %s %p)\n", node, debugstr_w(name), debugstr_w(uri), item);
1528
1529     if (!name) return E_INVALIDARG;
1530
1531     if (uri && *uri)
1532     {
1533         href = xmlchar_from_wchar(uri);
1534         if (!href) return E_OUTOFMEMORY;
1535     }
1536     else
1537         href = NULL;
1538
1539     nameA = xmlchar_from_wchar(name);
1540     if (!nameA)
1541     {
1542         heap_free(href);
1543         return E_OUTOFMEMORY;
1544     }
1545
1546     attr = xmlHasNsProp(node, nameA, href);
1547
1548     heap_free(nameA);
1549     heap_free(href);
1550
1551     if (!attr)
1552     {
1553         if (item) *item = NULL;
1554         return S_FALSE;
1555     }
1556
1557     if (item)
1558     {
1559         xmlUnlinkNode( (xmlNodePtr) attr );
1560         xmldoc_add_orphan( attr->doc, (xmlNodePtr) attr );
1561         *item = create_node( (xmlNodePtr) attr );
1562     }
1563     else
1564     {
1565         if (xmlRemoveProp(attr) == -1)
1566             ERR("xmlRemoveProp failed\n");
1567     }
1568
1569     return S_OK;
1570 }
1571
1572 static HRESULT domelem_remove_named_item(xmlNodePtr node, BSTR name, IXMLDOMNode **item)
1573 {
1574     TRACE("(%p)->(%s %p)\n", node, debugstr_w(name), item);
1575     return domelem_remove_qualified_item(node, name, NULL, item);
1576 }
1577
1578 static HRESULT domelem_get_item(const xmlNodePtr node, LONG index, IXMLDOMNode **item)
1579 {
1580     xmlAttrPtr curr;
1581     LONG attrIndex;
1582
1583     TRACE("(%p)->(%d %p)\n", node, index, item);
1584
1585     *item = NULL;
1586
1587     if (index < 0)
1588         return S_FALSE;
1589
1590     curr = node->properties;
1591
1592     for (attrIndex = 0; attrIndex < index; attrIndex++) {
1593         if (curr->next == NULL)
1594             return S_FALSE;
1595         else
1596             curr = curr->next;
1597     }
1598
1599     *item = create_node( (xmlNodePtr) curr );
1600
1601     return S_OK;
1602 }
1603
1604 static HRESULT domelem_get_length(const xmlNodePtr node, LONG *length)
1605 {
1606     xmlAttrPtr first;
1607     xmlAttrPtr curr;
1608     LONG attrCount;
1609
1610     TRACE("(%p)->(%p)\n", node, length);
1611
1612     if( !length )
1613         return E_INVALIDARG;
1614
1615     first = node->properties;
1616     if (first == NULL) {
1617         *length = 0;
1618         return S_OK;
1619     }
1620
1621     curr = first;
1622     attrCount = 1;
1623     while (curr->next) {
1624         attrCount++;
1625         curr = curr->next;
1626     }
1627     *length = attrCount;
1628
1629     return S_OK;
1630 }
1631
1632 static HRESULT domelem_next_node(const xmlNodePtr node, LONG *iter, IXMLDOMNode **nextNode)
1633 {
1634     xmlAttrPtr curr;
1635     LONG i;
1636
1637     TRACE("(%p)->(%d: %p)\n", node, *iter, nextNode);
1638
1639     *nextNode = NULL;
1640
1641     curr = node->properties;
1642
1643     for (i = 0; i < *iter; i++) {
1644         if (curr->next == NULL)
1645             return S_FALSE;
1646         else
1647             curr = curr->next;
1648     }
1649
1650     (*iter)++;
1651     *nextNode = create_node((xmlNodePtr)curr);
1652
1653     return S_OK;
1654 }
1655
1656 static const struct nodemap_funcs domelem_attr_map = {
1657     domelem_get_named_item,
1658     domelem_set_named_item,
1659     domelem_remove_named_item,
1660     domelem_get_item,
1661     domelem_get_length,
1662     domelem_get_qualified_item,
1663     domelem_remove_qualified_item,
1664     domelem_next_node
1665 };
1666
1667 static const tid_t domelem_iface_tids[] = {
1668     IXMLDOMElement_tid,
1669     0
1670 };
1671
1672 static dispex_static_data_t domelem_dispex = {
1673     NULL,
1674     IXMLDOMElement_tid,
1675     NULL,
1676     domelem_iface_tids
1677 };
1678
1679 IUnknown* create_element( xmlNodePtr element )
1680 {
1681     domelem *This;
1682
1683     This = heap_alloc( sizeof *This );
1684     if ( !This )
1685         return NULL;
1686
1687     This->IXMLDOMElement_iface.lpVtbl = &domelem_vtbl;
1688     This->ref = 1;
1689
1690     init_xmlnode(&This->node, element, (IXMLDOMNode*)&This->IXMLDOMElement_iface, &domelem_dispex);
1691
1692     return (IUnknown*)&This->IXMLDOMElement_iface;
1693 }
1694
1695 #endif