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