wined3d: Use wined3d_uint32_compare() in compare_sig().
[wine.git] / dlls / msxml3 / element.c
blobe1462c47d88d2a1f6c1c30b365934aef11fd5d47
1 /*
2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <stdarg.h>
24 #include <libxml/parser.h>
25 #include <libxml/xmlerror.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "ole2.h"
32 #include "msxml6.h"
34 #include "msxml_private.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
40 static const xmlChar DT_prefix[] = "dt";
41 static const xmlChar DT_nsURI[] = "urn:schemas-microsoft-com:datatypes";
43 typedef struct _domelem
45 xmlnode node;
46 IXMLDOMElement IXMLDOMElement_iface;
47 LONG ref;
48 } domelem;
50 static const struct nodemap_funcs domelem_attr_map;
52 static const tid_t domelem_se_tids[] = {
53 IXMLDOMNode_tid,
54 IXMLDOMElement_tid,
55 NULL_tid
58 static inline domelem *impl_from_IXMLDOMElement( IXMLDOMElement *iface )
60 return CONTAINING_RECORD(iface, domelem, IXMLDOMElement_iface);
63 static inline xmlNodePtr get_element( const domelem *This )
65 return This->node.node;
68 static HRESULT WINAPI domelem_QueryInterface(
69 IXMLDOMElement *iface,
70 REFIID riid,
71 void** ppvObject )
73 domelem *This = impl_from_IXMLDOMElement( iface );
75 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
77 if ( IsEqualGUID( riid, &IID_IXMLDOMElement ) ||
78 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
79 IsEqualGUID( riid, &IID_IDispatch ) ||
80 IsEqualGUID( riid, &IID_IUnknown ) )
82 *ppvObject = &This->IXMLDOMElement_iface;
84 else if(node_query_interface(&This->node, riid, ppvObject))
86 return *ppvObject ? S_OK : E_NOINTERFACE;
88 else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
90 return node_create_supporterrorinfo(domelem_se_tids, ppvObject);
92 else
94 TRACE("interface %s not implemented\n", debugstr_guid(riid));
95 *ppvObject = NULL;
96 return E_NOINTERFACE;
99 IUnknown_AddRef( (IUnknown*)*ppvObject );
100 return S_OK;
103 static ULONG WINAPI domelem_AddRef(
104 IXMLDOMElement *iface )
106 domelem *This = impl_from_IXMLDOMElement( iface );
107 LONG ref = InterlockedIncrement(&This->ref);
109 TRACE("(%p)->(%d)\n", This, ref);
111 return ref;
114 static ULONG WINAPI domelem_Release(
115 IXMLDOMElement *iface )
117 domelem *This = impl_from_IXMLDOMElement( iface );
118 ULONG ref = InterlockedDecrement(&This->ref);
120 TRACE("(%p)->(%d)\n", This, ref);
122 if(!ref) {
123 destroy_xmlnode(&This->node);
124 heap_free(This);
127 return ref;
130 static HRESULT WINAPI domelem_GetTypeInfoCount(
131 IXMLDOMElement *iface,
132 UINT* pctinfo )
134 domelem *This = impl_from_IXMLDOMElement( iface );
135 return IDispatchEx_GetTypeInfoCount(&This->node.dispex.IDispatchEx_iface, pctinfo);
138 static HRESULT WINAPI domelem_GetTypeInfo(
139 IXMLDOMElement *iface,
140 UINT iTInfo, LCID lcid,
141 ITypeInfo** ppTInfo )
143 domelem *This = impl_from_IXMLDOMElement( iface );
144 return IDispatchEx_GetTypeInfo(&This->node.dispex.IDispatchEx_iface,
145 iTInfo, lcid, ppTInfo);
148 static HRESULT WINAPI domelem_GetIDsOfNames(
149 IXMLDOMElement *iface,
150 REFIID riid, LPOLESTR* rgszNames,
151 UINT cNames, LCID lcid, DISPID* rgDispId )
153 domelem *This = impl_from_IXMLDOMElement( iface );
154 return IDispatchEx_GetIDsOfNames(&This->node.dispex.IDispatchEx_iface,
155 riid, rgszNames, cNames, lcid, rgDispId);
158 static HRESULT WINAPI domelem_Invoke(
159 IXMLDOMElement *iface,
160 DISPID dispIdMember, REFIID riid, LCID lcid,
161 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
162 EXCEPINFO* pExcepInfo, UINT* puArgErr )
164 domelem *This = impl_from_IXMLDOMElement( iface );
165 return IDispatchEx_Invoke(&This->node.dispex.IDispatchEx_iface,
166 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
169 static HRESULT WINAPI domelem_get_nodeName(
170 IXMLDOMElement *iface,
171 BSTR* p )
173 domelem *This = impl_from_IXMLDOMElement( iface );
175 TRACE("(%p)->(%p)\n", This, p);
177 return node_get_nodeName(&This->node, p);
180 static HRESULT WINAPI domelem_get_nodeValue(
181 IXMLDOMElement *iface,
182 VARIANT* value)
184 domelem *This = impl_from_IXMLDOMElement( iface );
186 TRACE("(%p)->(%p)\n", This, value);
188 if(!value)
189 return E_INVALIDARG;
191 V_VT(value) = VT_NULL;
192 V_BSTR(value) = NULL; /* tests show that we should do this */
193 return S_FALSE;
196 static HRESULT WINAPI domelem_put_nodeValue(
197 IXMLDOMElement *iface,
198 VARIANT value)
200 domelem *This = impl_from_IXMLDOMElement( iface );
201 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
202 return E_FAIL;
205 static HRESULT WINAPI domelem_get_nodeType(
206 IXMLDOMElement *iface,
207 DOMNodeType* domNodeType )
209 domelem *This = impl_from_IXMLDOMElement( iface );
211 TRACE("(%p)->(%p)\n", This, domNodeType);
213 *domNodeType = NODE_ELEMENT;
214 return S_OK;
217 static HRESULT WINAPI domelem_get_parentNode(
218 IXMLDOMElement *iface,
219 IXMLDOMNode** parent )
221 domelem *This = impl_from_IXMLDOMElement( iface );
223 TRACE("(%p)->(%p)\n", This, parent);
225 return node_get_parent(&This->node, parent);
228 static HRESULT WINAPI domelem_get_childNodes(
229 IXMLDOMElement *iface,
230 IXMLDOMNodeList** outList)
232 domelem *This = impl_from_IXMLDOMElement( iface );
234 TRACE("(%p)->(%p)\n", This, outList);
236 return node_get_child_nodes(&This->node, outList);
239 static HRESULT WINAPI domelem_get_firstChild(
240 IXMLDOMElement *iface,
241 IXMLDOMNode** domNode)
243 domelem *This = impl_from_IXMLDOMElement( iface );
245 TRACE("(%p)->(%p)\n", This, domNode);
247 return node_get_first_child(&This->node, domNode);
250 static HRESULT WINAPI domelem_get_lastChild(
251 IXMLDOMElement *iface,
252 IXMLDOMNode** domNode)
254 domelem *This = impl_from_IXMLDOMElement( iface );
256 TRACE("(%p)->(%p)\n", This, domNode);
258 return node_get_last_child(&This->node, domNode);
261 static HRESULT WINAPI domelem_get_previousSibling(
262 IXMLDOMElement *iface,
263 IXMLDOMNode** domNode)
265 domelem *This = impl_from_IXMLDOMElement( iface );
267 TRACE("(%p)->(%p)\n", This, domNode);
269 return node_get_previous_sibling(&This->node, domNode);
272 static HRESULT WINAPI domelem_get_nextSibling(
273 IXMLDOMElement *iface,
274 IXMLDOMNode** domNode)
276 domelem *This = impl_from_IXMLDOMElement( iface );
278 TRACE("(%p)->(%p)\n", This, domNode);
280 return node_get_next_sibling(&This->node, domNode);
283 static HRESULT WINAPI domelem_get_attributes(
284 IXMLDOMElement *iface,
285 IXMLDOMNamedNodeMap** map)
287 domelem *This = impl_from_IXMLDOMElement( iface );
289 TRACE("(%p)->(%p)\n", This, map);
291 *map = create_nodemap(This->node.node, &domelem_attr_map);
292 return S_OK;
295 static HRESULT WINAPI domelem_insertBefore(
296 IXMLDOMElement *iface,
297 IXMLDOMNode* newNode, VARIANT refChild,
298 IXMLDOMNode** old_node)
300 domelem *This = impl_from_IXMLDOMElement( iface );
301 DOMNodeType type;
302 HRESULT hr;
304 TRACE("(%p)->(%p %s %p)\n", This, newNode, debugstr_variant(&refChild), old_node);
306 if (!newNode) return E_INVALIDARG;
308 hr = IXMLDOMNode_get_nodeType(newNode, &type);
309 if (hr != S_OK) return hr;
311 TRACE("new node type %d\n", type);
312 switch (type)
314 case NODE_DOCUMENT:
315 case NODE_DOCUMENT_TYPE:
316 case NODE_ENTITY:
317 case NODE_NOTATION:
318 if (old_node) *old_node = NULL;
319 return E_FAIL;
320 default:
321 return node_insert_before(&This->node, newNode, &refChild, old_node);
325 static HRESULT WINAPI domelem_replaceChild(
326 IXMLDOMElement *iface,
327 IXMLDOMNode* newNode,
328 IXMLDOMNode* oldNode,
329 IXMLDOMNode** outOldNode)
331 domelem *This = impl_from_IXMLDOMElement( iface );
333 TRACE("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
335 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
338 static HRESULT WINAPI domelem_removeChild(
339 IXMLDOMElement *iface,
340 IXMLDOMNode *child, IXMLDOMNode **oldChild)
342 domelem *This = impl_from_IXMLDOMElement( iface );
343 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
344 return node_remove_child(&This->node, child, oldChild);
347 static HRESULT WINAPI domelem_appendChild(
348 IXMLDOMElement *iface,
349 IXMLDOMNode *child, IXMLDOMNode **outChild)
351 domelem *This = impl_from_IXMLDOMElement( iface );
352 TRACE("(%p)->(%p %p)\n", This, child, outChild);
353 return node_append_child(&This->node, child, outChild);
356 static HRESULT WINAPI domelem_hasChildNodes(
357 IXMLDOMElement *iface,
358 VARIANT_BOOL *ret)
360 domelem *This = impl_from_IXMLDOMElement( iface );
361 TRACE("(%p)->(%p)\n", This, ret);
362 return node_has_childnodes(&This->node, ret);
365 static HRESULT WINAPI domelem_get_ownerDocument(
366 IXMLDOMElement *iface,
367 IXMLDOMDocument **doc)
369 domelem *This = impl_from_IXMLDOMElement( iface );
370 TRACE("(%p)->(%p)\n", This, doc);
371 return node_get_owner_doc(&This->node, doc);
374 static HRESULT WINAPI domelem_cloneNode(
375 IXMLDOMElement *iface,
376 VARIANT_BOOL deep, IXMLDOMNode** outNode)
378 domelem *This = impl_from_IXMLDOMElement( iface );
379 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
380 return node_clone( &This->node, deep, outNode );
383 static HRESULT WINAPI domelem_get_nodeTypeString(
384 IXMLDOMElement *iface,
385 BSTR* p)
387 domelem *This = impl_from_IXMLDOMElement( iface );
388 static const WCHAR elementW[] = {'e','l','e','m','e','n','t',0};
390 TRACE("(%p)->(%p)\n", This, p);
392 return return_bstr(elementW, p);
395 static HRESULT WINAPI domelem_get_text(
396 IXMLDOMElement *iface,
397 BSTR* p)
399 domelem *This = impl_from_IXMLDOMElement( iface );
400 TRACE("(%p)->(%p)\n", This, p);
401 return node_get_text(&This->node, p);
404 static HRESULT WINAPI domelem_put_text(
405 IXMLDOMElement *iface,
406 BSTR p)
408 domelem *This = impl_from_IXMLDOMElement( iface );
409 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
410 return node_put_text( &This->node, p );
413 static HRESULT WINAPI domelem_get_specified(
414 IXMLDOMElement *iface,
415 VARIANT_BOOL* isSpecified)
417 domelem *This = impl_from_IXMLDOMElement( iface );
418 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
419 *isSpecified = VARIANT_TRUE;
420 return S_OK;
423 static HRESULT WINAPI domelem_get_definition(
424 IXMLDOMElement *iface,
425 IXMLDOMNode** definitionNode)
427 domelem *This = impl_from_IXMLDOMElement( iface );
428 FIXME("(%p)->(%p)\n", This, definitionNode);
429 return E_NOTIMPL;
432 static inline BYTE hex_to_byte(xmlChar c)
434 if(c <= '9') return c-'0';
435 if(c <= 'F') return c-'A'+10;
436 return c-'a'+10;
439 static inline BYTE base64_to_byte(xmlChar c)
441 if(c == '+') return 62;
442 if(c == '/') return 63;
443 if(c <= '9') return c-'0'+52;
444 if(c <= 'Z') return c-'A';
445 return c-'a'+26;
448 static inline HRESULT variant_from_dt(XDR_DT dt, xmlChar* str, VARIANT* v)
450 VARIANT src;
451 HRESULT hr = S_OK;
452 BOOL handled = FALSE;
454 VariantInit(&src);
456 switch (dt)
458 case DT_INVALID:
459 case DT_STRING:
460 case DT_NMTOKEN:
461 case DT_NMTOKENS:
462 case DT_NUMBER:
463 case DT_URI:
464 case DT_UUID:
466 V_VT(v) = VT_BSTR;
467 V_BSTR(v) = bstr_from_xmlChar(str);
469 if(!V_BSTR(v))
470 return E_OUTOFMEMORY;
471 handled = TRUE;
473 break;
474 case DT_DATE:
475 case DT_DATE_TZ:
476 case DT_DATETIME:
477 case DT_DATETIME_TZ:
478 case DT_TIME:
479 case DT_TIME_TZ:
481 WCHAR *p, *e;
482 SYSTEMTIME st;
483 DOUBLE date = 0.0;
485 st.wYear = 1899;
486 st.wMonth = 12;
487 st.wDay = 30;
488 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
490 V_VT(&src) = VT_BSTR;
491 V_BSTR(&src) = bstr_from_xmlChar(str);
493 if(!V_BSTR(&src))
494 return E_OUTOFMEMORY;
496 p = V_BSTR(&src);
497 e = p + SysStringLen(V_BSTR(&src));
499 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
501 st.wYear = wcstol(p, NULL, 10);
502 st.wMonth = wcstol(p+5, NULL, 10);
503 st.wDay = wcstol(p+8, NULL, 10);
504 p += 10;
506 if(*p == 'T') p++;
509 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
511 st.wHour = wcstol(p, NULL, 10);
512 st.wMinute = wcstol(p+3, NULL, 10);
513 st.wSecond = wcstol(p+6, NULL, 10);
514 p += 8;
516 if(*p == '.')
518 p++;
519 while (*p >= '0' && *p <= '9') p++;
523 SystemTimeToVariantTime(&st, &date);
524 V_VT(v) = VT_DATE;
525 V_DATE(v) = date;
527 if(*p == '+') /* parse timezone offset (+hh:mm) */
528 V_DATE(v) += (DOUBLE)wcstol(p+1, NULL, 10)/24 + (DOUBLE)wcstol(p+4, NULL, 10)/1440;
529 else if(*p == '-') /* parse timezone offset (-hh:mm) */
530 V_DATE(v) -= (DOUBLE)wcstol(p+1, NULL, 10)/24 + (DOUBLE)wcstol(p+4, NULL, 10)/1440;
532 VariantClear(&src);
533 handled = TRUE;
535 break;
536 case DT_BIN_HEX:
538 SAFEARRAYBOUND sab;
539 int i, len;
541 len = xmlStrlen(str)/2;
542 sab.lLbound = 0;
543 sab.cElements = len;
545 V_VT(v) = (VT_ARRAY|VT_UI1);
546 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
548 if(!V_ARRAY(v))
549 return E_OUTOFMEMORY;
551 for(i=0; i<len; i++)
552 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
553 + hex_to_byte(str[2*i+1]);
554 handled = TRUE;
556 break;
557 case DT_BIN_BASE64:
559 SAFEARRAYBOUND sab;
560 xmlChar *c1, *c2;
561 int i, len;
563 /* remove all formatting chars */
564 c1 = c2 = str;
565 len = 0;
566 while (*c2)
568 if ( *c2 == ' ' || *c2 == '\t' ||
569 *c2 == '\n' || *c2 == '\r' )
571 c2++;
572 continue;
574 *c1++ = *c2++;
575 len++;
578 /* skip padding */
579 if(str[len-2] == '=') i = 2;
580 else if(str[len-1] == '=') i = 1;
581 else i = 0;
583 sab.lLbound = 0;
584 sab.cElements = len/4*3-i;
586 V_VT(v) = (VT_ARRAY|VT_UI1);
587 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
589 if(!V_ARRAY(v))
590 return E_OUTOFMEMORY;
592 for(i=0; i<len/4; i++)
594 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
595 + (base64_to_byte(str[4*i+1])>>4);
596 if(3*i+1 < sab.cElements)
597 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
598 + (base64_to_byte(str[4*i+2])>>2);
599 if(3*i+2 < sab.cElements)
600 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
601 + base64_to_byte(str[4*i+3]);
603 handled = TRUE;
605 break;
606 case DT_BOOLEAN:
607 V_VT(v) = VT_BOOL;
608 break;
609 case DT_FIXED_14_4:
610 V_VT(v) = VT_CY;
611 break;
612 case DT_I1:
613 V_VT(v) = VT_I1;
614 break;
615 case DT_I2:
616 V_VT(v) = VT_I2;
617 break;
618 case DT_I4:
619 case DT_INT:
620 V_VT(v) = VT_I4;
621 break;
622 case DT_I8:
623 V_VT(v) = VT_I8;
624 break;
625 case DT_R4:
626 V_VT(v) = VT_R4;
627 break;
628 case DT_FLOAT:
629 case DT_R8:
630 V_VT(v) = VT_R8;
631 break;
632 case DT_UI1:
633 V_VT(v) = VT_UI1;
634 break;
635 case DT_UI2:
636 V_VT(v) = VT_UI2;
637 break;
638 case DT_UI4:
639 V_VT(v) = VT_UI4;
640 break;
641 case DT_UI8:
642 V_VT(v) = VT_UI8;
643 break;
644 case DT_CHAR:
645 case DT_ENTITY:
646 case DT_ENTITIES:
647 case DT_ENUMERATION:
648 case DT_ID:
649 case DT_IDREF:
650 case DT_IDREFS:
651 case DT_NOTATION:
652 FIXME("need to handle dt:%s\n", debugstr_dt(dt));
653 V_VT(v) = VT_BSTR;
654 V_BSTR(v) = bstr_from_xmlChar(str);
655 if (!V_BSTR(v))
656 return E_OUTOFMEMORY;
657 handled = TRUE;
658 break;
659 default:
660 WARN("unknown type %d\n", dt);
663 if (!handled)
665 V_VT(&src) = VT_BSTR;
666 V_BSTR(&src) = bstr_from_xmlChar(str);
668 if(!V_BSTR(&src))
669 return E_OUTOFMEMORY;
671 hr = VariantChangeTypeEx(v, &src,
672 MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
673 VariantClear(&src);
675 return hr;
678 static XDR_DT element_get_dt(xmlNodePtr node)
680 XDR_DT dt = DT_INVALID;
682 TRACE("(%p)\n", node);
683 if(node->type != XML_ELEMENT_NODE)
685 FIXME("invalid element node\n");
686 return dt;
689 if (node->ns && xmlStrEqual(node->ns->href, DT_nsURI))
691 dt = str_to_dt(node->name, -1);
693 else
695 xmlChar* pVal = xmlGetNsProp(node, BAD_CAST "dt", DT_nsURI);
696 if (pVal)
698 dt = str_to_dt(pVal, -1);
699 xmlFree(pVal);
701 else if (node->doc)
703 IXMLDOMDocument3* doc = (IXMLDOMDocument3*)create_domdoc((xmlNodePtr)node->doc);
704 if (doc)
706 VARIANT v;
707 VariantInit(&v);
709 if (IXMLDOMDocument3_get_schemas(doc, &v) == S_OK &&
710 V_VT(&v) == VT_DISPATCH)
712 dt = SchemaCache_get_node_dt((IXMLDOMSchemaCollection2*)V_DISPATCH(&v), node);
714 VariantClear(&v);
715 IXMLDOMDocument3_Release(doc);
720 TRACE("=> dt:%s\n", debugstr_dt(dt));
721 return dt;
724 static HRESULT WINAPI domelem_get_nodeTypedValue(
725 IXMLDOMElement *iface,
726 VARIANT* v)
728 domelem *This = impl_from_IXMLDOMElement( iface );
729 XDR_DT dt;
730 xmlChar* content;
731 HRESULT hr;
733 TRACE("(%p)->(%p)\n", This, v);
735 if(!v) return E_INVALIDARG;
737 V_VT(v) = VT_NULL;
739 dt = element_get_dt(get_element(This));
740 content = xmlNodeGetContent(get_element(This));
741 hr = variant_from_dt(dt, content, v);
742 xmlFree(content);
744 return hr;
747 static HRESULT encode_base64(const BYTE *buf, int len, BSTR *ret)
749 static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
750 const BYTE *d = buf;
751 int bytes, pad_bytes, div;
752 DWORD needed;
753 WCHAR *ptr;
755 bytes = (len*8 + 5)/6;
756 pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
758 TRACE("%d, bytes is %d, pad bytes is %d\n", len, bytes, pad_bytes);
759 needed = bytes + pad_bytes + 1;
761 *ret = SysAllocStringLen(NULL, needed);
762 if (!*ret) return E_OUTOFMEMORY;
764 /* Three bytes of input give 4 chars of output */
765 div = len / 3;
767 ptr = *ret;
768 while (div > 0)
770 /* first char is the first 6 bits of the first byte*/
771 *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
772 /* second char is the last 2 bits of the first byte and the first 4
773 * bits of the second byte */
774 *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
775 /* third char is the last 4 bits of the second byte and the first 2
776 * bits of the third byte */
777 *ptr++ = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)];
778 /* fourth char is the remaining 6 bits of the third byte */
779 *ptr++ = b64[ d[2] & 0x3f];
780 d += 3;
781 div--;
784 switch (pad_bytes)
786 case 1:
787 /* first char is the first 6 bits of the first byte*/
788 *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
789 /* second char is the last 2 bits of the first byte and the first 4
790 * bits of the second byte */
791 *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
792 /* third char is the last 4 bits of the second byte padded with
793 * two zeroes */
794 *ptr++ = b64[ ((d[1] << 2) & 0x3c) ];
795 /* fourth char is a = to indicate one byte of padding */
796 *ptr++ = '=';
797 break;
798 case 2:
799 /* first char is the first 6 bits of the first byte*/
800 *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
801 /* second char is the last 2 bits of the first byte padded with
802 * four zeroes*/
803 *ptr++ = b64[ ((d[0] << 4) & 0x30)];
804 /* third char is = to indicate padding */
805 *ptr++ = '=';
806 /* fourth char is = to indicate padding */
807 *ptr++ = '=';
808 break;
811 return S_OK;
814 static HRESULT encode_binhex(const BYTE *buf, int len, BSTR *ret)
816 static const char byte_to_hex[16] = "0123456789abcdef";
817 int i;
819 *ret = SysAllocStringLen(NULL, len*2);
820 if (!*ret) return E_OUTOFMEMORY;
822 for (i = 0; i < len; i++)
824 (*ret)[2*i] = byte_to_hex[buf[i] >> 4];
825 (*ret)[2*i+1] = byte_to_hex[0x0f & buf[i]];
828 return S_OK;
831 static HRESULT WINAPI domelem_put_nodeTypedValue(
832 IXMLDOMElement *iface,
833 VARIANT value)
835 domelem *This = impl_from_IXMLDOMElement( iface );
836 XDR_DT dt;
837 HRESULT hr;
839 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
841 dt = element_get_dt(get_element(This));
842 switch (dt)
844 /* for untyped node coerce to BSTR and set */
845 case DT_INVALID:
846 case DT_INT:
847 if (V_VT(&value) != VT_BSTR)
849 VARIANT content;
850 VariantInit(&content);
851 hr = VariantChangeType(&content, &value, 0, VT_BSTR);
852 if (hr == S_OK)
854 hr = node_set_content(&This->node, V_BSTR(&content));
855 VariantClear(&content);
858 else
859 hr = node_set_content(&This->node, V_BSTR(&value));
860 break;
861 case DT_BIN_BASE64:
862 if (V_VT(&value) == VT_BSTR)
863 hr = node_set_content(&This->node, V_BSTR(&value));
864 else if (V_VT(&value) == (VT_UI1|VT_ARRAY))
866 UINT dim = SafeArrayGetDim(V_ARRAY(&value));
867 LONG lbound, ubound;
868 BSTR encoded;
869 BYTE *ptr;
870 int len;
872 if (dim > 1)
873 FIXME("unexpected array dimension count %u\n", dim);
875 SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
876 SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
878 len = (ubound - lbound + 1)*SafeArrayGetElemsize(V_ARRAY(&value));
880 hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
881 if (FAILED(hr)) return hr;
883 hr = encode_base64(ptr, len, &encoded);
884 SafeArrayUnaccessData(V_ARRAY(&value));
885 if (FAILED(hr)) return hr;
887 hr = node_set_content(&This->node, encoded);
888 SysFreeString(encoded);
890 else
892 FIXME("unhandled variant type %d for dt:%s\n", V_VT(&value), debugstr_dt(dt));
893 return E_NOTIMPL;
895 break;
896 case DT_BIN_HEX:
897 if (V_VT(&value) == (VT_UI1|VT_ARRAY))
899 UINT dim = SafeArrayGetDim(V_ARRAY(&value));
900 LONG lbound, ubound;
901 BSTR encoded;
902 BYTE *ptr;
903 int len;
905 if (dim > 1)
906 FIXME("unexpected array dimension count %u\n", dim);
908 SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
909 SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
911 len = (ubound - lbound + 1)*SafeArrayGetElemsize(V_ARRAY(&value));
913 hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
914 if (FAILED(hr)) return hr;
916 hr = encode_binhex(ptr, len, &encoded);
917 SafeArrayUnaccessData(V_ARRAY(&value));
918 if (FAILED(hr)) return hr;
920 hr = node_set_content(&This->node, encoded);
921 SysFreeString(encoded);
923 else
925 FIXME("unhandled variant type %d for dt:%s\n", V_VT(&value), debugstr_dt(dt));
926 return E_NOTIMPL;
928 break;
929 default:
930 FIXME("not implemented for dt:%s\n", debugstr_dt(dt));
931 return E_NOTIMPL;
934 return hr;
937 static HRESULT WINAPI domelem_get_dataType(
938 IXMLDOMElement *iface,
939 VARIANT* typename)
941 domelem *This = impl_from_IXMLDOMElement( iface );
942 XDR_DT dt;
944 TRACE("(%p)->(%p)\n", This, typename);
946 if (!typename)
947 return E_INVALIDARG;
949 dt = element_get_dt(get_element(This));
950 switch (dt)
952 case DT_BIN_BASE64:
953 case DT_BIN_HEX:
954 case DT_BOOLEAN:
955 case DT_CHAR:
956 case DT_DATE:
957 case DT_DATE_TZ:
958 case DT_DATETIME:
959 case DT_DATETIME_TZ:
960 case DT_FIXED_14_4:
961 case DT_FLOAT:
962 case DT_I1:
963 case DT_I2:
964 case DT_I4:
965 case DT_I8:
966 case DT_INT:
967 case DT_NUMBER:
968 case DT_R4:
969 case DT_R8:
970 case DT_TIME:
971 case DT_TIME_TZ:
972 case DT_UI1:
973 case DT_UI2:
974 case DT_UI4:
975 case DT_UI8:
976 case DT_URI:
977 case DT_UUID:
978 V_VT(typename) = VT_BSTR;
979 V_BSTR(typename) = SysAllocString(dt_to_bstr(dt));
981 if (!V_BSTR(typename))
982 return E_OUTOFMEMORY;
983 break;
984 default:
985 /* Other types (DTD equivalents) do not return anything here,
986 * but the pointer part of the VARIANT is set to NULL */
987 V_VT(typename) = VT_NULL;
988 V_BSTR(typename) = NULL;
989 break;
991 return (V_VT(typename) != VT_NULL) ? S_OK : S_FALSE;
994 static HRESULT WINAPI domelem_put_dataType(
995 IXMLDOMElement *iface,
996 BSTR dtName)
998 domelem *This = impl_from_IXMLDOMElement( iface );
999 HRESULT hr = E_FAIL;
1000 xmlChar *str;
1001 XDR_DT dt;
1003 TRACE("(%p)->(%s)\n", This, debugstr_w(dtName));
1005 if(dtName == NULL)
1006 return E_INVALIDARG;
1008 dt = bstr_to_dt(dtName, -1);
1010 /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
1011 This applies to changing types (string->bool) or setting a new one
1013 str = xmlNodeGetContent(get_element(This));
1014 hr = dt_validate(dt, str);
1015 xmlFree(str);
1017 /* Check all supported types. */
1018 if (hr == S_OK)
1020 switch (dt)
1022 case DT_BIN_BASE64:
1023 case DT_BIN_HEX:
1024 case DT_BOOLEAN:
1025 case DT_CHAR:
1026 case DT_DATE:
1027 case DT_DATE_TZ:
1028 case DT_DATETIME:
1029 case DT_DATETIME_TZ:
1030 case DT_FIXED_14_4:
1031 case DT_FLOAT:
1032 case DT_I1:
1033 case DT_I2:
1034 case DT_I4:
1035 case DT_I8:
1036 case DT_INT:
1037 case DT_NMTOKEN:
1038 case DT_NMTOKENS:
1039 case DT_NUMBER:
1040 case DT_R4:
1041 case DT_R8:
1042 case DT_STRING:
1043 case DT_TIME:
1044 case DT_TIME_TZ:
1045 case DT_UI1:
1046 case DT_UI2:
1047 case DT_UI4:
1048 case DT_UI8:
1049 case DT_URI:
1050 case DT_UUID:
1052 xmlAttrPtr attr = xmlHasNsProp(get_element(This), DT_prefix, DT_nsURI);
1053 if (attr)
1055 attr = xmlSetNsProp(get_element(This), attr->ns, DT_prefix, dt_to_str(dt));
1056 hr = S_OK;
1058 else
1060 xmlNsPtr ns = xmlNewNs(get_element(This), DT_nsURI, DT_prefix);
1061 if (ns)
1063 attr = xmlNewNsProp(get_element(This), ns, DT_prefix, dt_to_str(dt));
1064 if (attr)
1066 xmlAddChild(get_element(This), (xmlNodePtr)attr);
1067 hr = S_OK;
1069 else
1070 ERR("Failed to create Attribute\n");
1072 else
1073 ERR("Failed to create Namespace\n");
1076 break;
1077 default:
1078 FIXME("need to handle dt:%s\n", debugstr_dt(dt));
1079 break;
1083 return hr;
1086 static HRESULT WINAPI domelem_get_xml(
1087 IXMLDOMElement *iface,
1088 BSTR* p)
1090 domelem *This = impl_from_IXMLDOMElement( iface );
1092 TRACE("(%p)->(%p)\n", This, p);
1094 return node_get_xml(&This->node, TRUE, p);
1097 static HRESULT WINAPI domelem_transformNode(
1098 IXMLDOMElement *iface,
1099 IXMLDOMNode *node, BSTR *p)
1101 domelem *This = impl_from_IXMLDOMElement( iface );
1102 TRACE("(%p)->(%p %p)\n", This, node, p);
1103 return node_transform_node(&This->node, node, p);
1106 static HRESULT WINAPI domelem_selectNodes(
1107 IXMLDOMElement *iface,
1108 BSTR p, IXMLDOMNodeList** outList)
1110 domelem *This = impl_from_IXMLDOMElement( iface );
1111 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1112 return node_select_nodes(&This->node, p, outList);
1115 static HRESULT WINAPI domelem_selectSingleNode(
1116 IXMLDOMElement *iface,
1117 BSTR p, IXMLDOMNode** outNode)
1119 domelem *This = impl_from_IXMLDOMElement( iface );
1120 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1121 return node_select_singlenode(&This->node, p, outNode);
1124 static HRESULT WINAPI domelem_get_parsed(
1125 IXMLDOMElement *iface,
1126 VARIANT_BOOL* isParsed)
1128 domelem *This = impl_from_IXMLDOMElement( iface );
1129 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1130 *isParsed = VARIANT_TRUE;
1131 return S_OK;
1134 static HRESULT WINAPI domelem_get_namespaceURI(
1135 IXMLDOMElement *iface,
1136 BSTR* p)
1138 domelem *This = impl_from_IXMLDOMElement( iface );
1139 TRACE("(%p)->(%p)\n", This, p);
1140 return node_get_namespaceURI(&This->node, p);
1143 static HRESULT WINAPI domelem_get_prefix(
1144 IXMLDOMElement *iface,
1145 BSTR* prefix)
1147 domelem *This = impl_from_IXMLDOMElement( iface );
1148 TRACE("(%p)->(%p)\n", This, prefix);
1149 return node_get_prefix( &This->node, prefix );
1152 static HRESULT WINAPI domelem_get_baseName(
1153 IXMLDOMElement *iface,
1154 BSTR* name)
1156 domelem *This = impl_from_IXMLDOMElement( iface );
1157 TRACE("(%p)->(%p)\n", This, name);
1158 return node_get_base_name( &This->node, name );
1161 static HRESULT WINAPI domelem_transformNodeToObject(
1162 IXMLDOMElement *iface,
1163 IXMLDOMNode* domNode, VARIANT var1)
1165 domelem *This = impl_from_IXMLDOMElement( iface );
1166 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1167 return E_NOTIMPL;
1170 static HRESULT WINAPI domelem_get_tagName(
1171 IXMLDOMElement *iface,
1172 BSTR* p)
1174 domelem *This = impl_from_IXMLDOMElement( iface );
1175 xmlNodePtr element;
1176 const xmlChar *prefix;
1177 xmlChar *qname;
1179 TRACE("(%p)->(%p)\n", This, p );
1181 if (!p) return E_INVALIDARG;
1183 element = get_element( This );
1184 if ( !element )
1185 return E_FAIL;
1187 prefix = element->ns ? element->ns->prefix : NULL;
1188 qname = xmlBuildQName(element->name, prefix, NULL, 0);
1190 *p = bstr_from_xmlChar(qname);
1191 if (qname != element->name) xmlFree(qname);
1193 return *p ? S_OK : E_OUTOFMEMORY;
1196 static HRESULT WINAPI domelem_getAttribute(
1197 IXMLDOMElement *iface,
1198 BSTR name, VARIANT* value)
1200 domelem *This = impl_from_IXMLDOMElement( iface );
1201 xmlNodePtr element;
1202 xmlChar *xml_name, *xml_value = NULL;
1203 xmlChar *local, *prefix;
1204 HRESULT hr = S_FALSE;
1205 xmlNsPtr ns;
1207 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), value);
1209 if(!value || !name)
1210 return E_INVALIDARG;
1212 element = get_element( This );
1213 if ( !element )
1214 return E_FAIL;
1216 V_BSTR(value) = NULL;
1217 V_VT(value) = VT_NULL;
1219 xml_name = xmlchar_from_wchar( name );
1221 if(!xmlValidateNameValue(xml_name))
1222 hr = E_FAIL;
1223 else
1225 if ((local = xmlSplitQName2(xml_name, &prefix)))
1227 if (xmlStrEqual(prefix, BAD_CAST "xmlns"))
1229 ns = xmlSearchNs(element->doc, element, local);
1230 if (ns)
1231 xml_value = xmlStrdup(ns->href);
1233 else
1235 ns = xmlSearchNs(element->doc, element, prefix);
1236 if (ns)
1237 xml_value = xmlGetNsProp(element, local, ns->href);
1240 xmlFree(prefix);
1241 xmlFree(local);
1243 else
1244 xml_value = xmlGetNsProp(element, xml_name, NULL);
1247 heap_free(xml_name);
1248 if(xml_value)
1250 V_VT(value) = VT_BSTR;
1251 V_BSTR(value) = bstr_from_xmlChar( xml_value );
1252 xmlFree(xml_value);
1253 hr = S_OK;
1256 return hr;
1259 static HRESULT WINAPI domelem_setAttribute(
1260 IXMLDOMElement *iface,
1261 BSTR name, VARIANT value)
1263 domelem *This = impl_from_IXMLDOMElement( iface );
1264 xmlChar *xml_name, *xml_value, *local, *prefix;
1265 xmlNodePtr element;
1266 HRESULT hr = S_OK;
1268 TRACE("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_variant(&value));
1270 element = get_element( This );
1271 if ( !element )
1272 return E_FAIL;
1274 if (V_VT(&value) != VT_BSTR)
1276 VARIANT var;
1278 VariantInit(&var);
1279 hr = VariantChangeType(&var, &value, 0, VT_BSTR);
1280 if (hr != S_OK)
1282 FIXME("VariantChangeType failed\n");
1283 return hr;
1286 xml_value = xmlchar_from_wchar(V_BSTR(&var));
1287 VariantClear(&var);
1289 else
1290 xml_value = xmlchar_from_wchar(V_BSTR(&value));
1292 xml_name = xmlchar_from_wchar( name );
1294 if ((local = xmlSplitQName2(xml_name, &prefix)))
1296 static const xmlChar* xmlnsA = (const xmlChar*)"xmlns";
1297 xmlNsPtr ns = NULL;
1299 /* it's not allowed to modify existing namespace definition */
1300 if (xmlStrEqual(prefix, xmlnsA))
1301 ns = xmlSearchNs(element->doc, element, local);
1303 xmlFree(prefix);
1304 xmlFree(local);
1306 if (ns)
1308 int cmp = xmlStrEqual(ns->href, xml_value);
1309 heap_free(xml_value);
1310 heap_free(xml_name);
1311 return cmp ? S_OK : E_INVALIDARG;
1315 if (!xmlSetNsProp(element, NULL, xml_name, xml_value))
1316 hr = E_FAIL;
1318 heap_free(xml_value);
1319 heap_free(xml_name);
1321 return hr;
1324 static HRESULT WINAPI domelem_removeAttribute(
1325 IXMLDOMElement *iface,
1326 BSTR p)
1328 domelem *This = impl_from_IXMLDOMElement( iface );
1329 IXMLDOMNamedNodeMap *attr;
1330 HRESULT hr;
1332 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1334 hr = IXMLDOMElement_get_attributes(iface, &attr);
1335 if (hr != S_OK) return hr;
1337 hr = IXMLDOMNamedNodeMap_removeNamedItem(attr, p, NULL);
1338 IXMLDOMNamedNodeMap_Release(attr);
1340 return hr;
1343 static HRESULT WINAPI domelem_getAttributeNode(
1344 IXMLDOMElement *iface,
1345 BSTR p, IXMLDOMAttribute** attributeNode )
1347 domelem *This = impl_from_IXMLDOMElement( iface );
1348 xmlChar *local, *prefix, *nameA;
1349 HRESULT hr = S_FALSE;
1350 xmlNodePtr element;
1351 xmlAttrPtr attr;
1353 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), attributeNode);
1355 element = get_element( This );
1356 if (!element) return E_FAIL;
1358 if (attributeNode) *attributeNode = NULL;
1360 nameA = xmlchar_from_wchar(p);
1361 if (!xmlValidateNameValue(nameA))
1363 heap_free(nameA);
1364 return E_FAIL;
1367 if (!attributeNode)
1369 heap_free(nameA);
1370 return S_FALSE;
1373 *attributeNode = NULL;
1375 local = xmlSplitQName2(nameA, &prefix);
1377 if (local)
1379 /* try to get namespace for supplied qualified name */
1380 xmlNsPtr ns = xmlSearchNs(element->doc, element, prefix);
1381 xmlFree(prefix);
1383 attr = xmlHasNsProp(element, local, ns ? ns->href : NULL);
1384 xmlFree(local);
1386 else
1388 attr = xmlHasProp(element, nameA);
1389 /* attribute has attached namespace and we requested non-qualified
1390 name - it's a failure case */
1391 if (attr && attr->ns) attr = NULL;
1394 heap_free(nameA);
1396 if (attr)
1398 IUnknown *unk = create_attribute((xmlNodePtr)attr, FALSE);
1399 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMAttribute, (void**)attributeNode);
1400 IUnknown_Release(unk);
1403 return hr;
1406 static HRESULT WINAPI domelem_setAttributeNode(
1407 IXMLDOMElement *iface,
1408 IXMLDOMAttribute* attribute,
1409 IXMLDOMAttribute** old)
1411 domelem *This = impl_from_IXMLDOMElement( iface );
1412 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
1413 xmlChar *name, *value;
1414 BSTR nameW, prefix;
1415 xmlnode *attr_node;
1416 xmlAttrPtr attr;
1417 VARIANT valueW;
1418 HRESULT hr;
1420 FIXME("(%p)->(%p %p): semi-stub\n", This, attribute, old);
1422 if (!attribute) return E_INVALIDARG;
1424 attr_node = get_node_obj((IXMLDOMNode*)attribute);
1425 if (!attr_node) return E_FAIL;
1427 if (attr_node->parent)
1429 WARN("attempt to add already used attribute\n");
1430 return E_FAIL;
1433 hr = IXMLDOMAttribute_get_nodeName(attribute, &nameW);
1434 if (hr != S_OK) return hr;
1436 /* adding xmlns attribute doesn't change a tree or existing namespace definition */
1437 if (!wcscmp(nameW, xmlnsW))
1439 SysFreeString(nameW);
1440 return DISP_E_UNKNOWNNAME;
1443 hr = IXMLDOMAttribute_get_nodeValue(attribute, &valueW);
1444 if (hr != S_OK)
1446 SysFreeString(nameW);
1447 return hr;
1450 if (old) *old = NULL;
1452 TRACE("attribute: %s=%s\n", debugstr_w(nameW), debugstr_w(V_BSTR(&valueW)));
1454 hr = IXMLDOMAttribute_get_prefix(attribute, &prefix);
1455 if (hr == S_OK)
1457 FIXME("namespaces not supported: %s\n", debugstr_w(prefix));
1458 SysFreeString(prefix);
1461 name = xmlchar_from_wchar(nameW);
1462 value = xmlchar_from_wchar(V_BSTR(&valueW));
1464 if (!name || !value)
1466 SysFreeString(nameW);
1467 VariantClear(&valueW);
1468 heap_free(name);
1469 heap_free(value);
1470 return E_OUTOFMEMORY;
1473 attr = xmlSetNsProp(get_element(This), NULL, name, value);
1474 if (attr)
1475 attr_node->parent = (IXMLDOMNode*)iface;
1477 SysFreeString(nameW);
1478 VariantClear(&valueW);
1479 heap_free(name);
1480 heap_free(value);
1482 return attr ? S_OK : E_FAIL;
1485 static HRESULT WINAPI domelem_removeAttributeNode(
1486 IXMLDOMElement *iface,
1487 IXMLDOMAttribute* domAttribute,
1488 IXMLDOMAttribute** attributeNode)
1490 domelem *This = impl_from_IXMLDOMElement( iface );
1491 FIXME("(%p)->(%p %p)\n", This, domAttribute, attributeNode);
1492 return E_NOTIMPL;
1495 static HRESULT WINAPI domelem_getElementsByTagName(
1496 IXMLDOMElement *iface,
1497 BSTR tagName, IXMLDOMNodeList** resultList)
1499 domelem *This = impl_from_IXMLDOMElement( iface );
1500 xmlChar *query;
1501 HRESULT hr;
1502 BOOL XPath;
1504 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1506 if (!tagName || !resultList) return E_INVALIDARG;
1508 XPath = is_xpathmode(get_element(This)->doc);
1509 set_xpathmode(get_element(This)->doc, TRUE);
1510 query = tagName_to_XPath(tagName);
1511 hr = create_selection(get_element(This), query, resultList);
1512 xmlFree(query);
1513 set_xpathmode(get_element(This)->doc, XPath);
1515 return hr;
1518 static HRESULT WINAPI domelem_normalize(
1519 IXMLDOMElement *iface )
1521 domelem *This = impl_from_IXMLDOMElement( iface );
1522 FIXME("%p\n", This);
1523 return E_NOTIMPL;
1526 static const struct IXMLDOMElementVtbl domelem_vtbl =
1528 domelem_QueryInterface,
1529 domelem_AddRef,
1530 domelem_Release,
1531 domelem_GetTypeInfoCount,
1532 domelem_GetTypeInfo,
1533 domelem_GetIDsOfNames,
1534 domelem_Invoke,
1535 domelem_get_nodeName,
1536 domelem_get_nodeValue,
1537 domelem_put_nodeValue,
1538 domelem_get_nodeType,
1539 domelem_get_parentNode,
1540 domelem_get_childNodes,
1541 domelem_get_firstChild,
1542 domelem_get_lastChild,
1543 domelem_get_previousSibling,
1544 domelem_get_nextSibling,
1545 domelem_get_attributes,
1546 domelem_insertBefore,
1547 domelem_replaceChild,
1548 domelem_removeChild,
1549 domelem_appendChild,
1550 domelem_hasChildNodes,
1551 domelem_get_ownerDocument,
1552 domelem_cloneNode,
1553 domelem_get_nodeTypeString,
1554 domelem_get_text,
1555 domelem_put_text,
1556 domelem_get_specified,
1557 domelem_get_definition,
1558 domelem_get_nodeTypedValue,
1559 domelem_put_nodeTypedValue,
1560 domelem_get_dataType,
1561 domelem_put_dataType,
1562 domelem_get_xml,
1563 domelem_transformNode,
1564 domelem_selectNodes,
1565 domelem_selectSingleNode,
1566 domelem_get_parsed,
1567 domelem_get_namespaceURI,
1568 domelem_get_prefix,
1569 domelem_get_baseName,
1570 domelem_transformNodeToObject,
1571 domelem_get_tagName,
1572 domelem_getAttribute,
1573 domelem_setAttribute,
1574 domelem_removeAttribute,
1575 domelem_getAttributeNode,
1576 domelem_setAttributeNode,
1577 domelem_removeAttributeNode,
1578 domelem_getElementsByTagName,
1579 domelem_normalize,
1582 static HRESULT domelem_get_qualified_item(const xmlNodePtr node, BSTR name, BSTR uri,
1583 IXMLDOMNode **item)
1585 xmlAttrPtr attr;
1586 xmlChar *nameA;
1587 xmlChar *href;
1589 TRACE("(%p)->(%s %s %p)\n", node, debugstr_w(name), debugstr_w(uri), item);
1591 if (!name || !item) return E_INVALIDARG;
1593 if (uri && *uri)
1595 href = xmlchar_from_wchar(uri);
1596 if (!href) return E_OUTOFMEMORY;
1598 else
1599 href = NULL;
1601 nameA = xmlchar_from_wchar(name);
1602 if (!nameA)
1604 heap_free(href);
1605 return E_OUTOFMEMORY;
1608 attr = xmlHasNsProp(node, nameA, href);
1610 heap_free(nameA);
1611 heap_free(href);
1613 if (!attr)
1615 *item = NULL;
1616 return S_FALSE;
1619 *item = create_node((xmlNodePtr)attr);
1621 return S_OK;
1624 static HRESULT domelem_get_named_item(const xmlNodePtr node, BSTR name, IXMLDOMNode **item)
1626 xmlChar *nameA, *local, *prefix;
1627 BSTR uriW, localW;
1628 xmlNsPtr ns;
1629 HRESULT hr;
1631 TRACE("(%p)->(%s %p)\n", node, debugstr_w(name), item );
1633 nameA = xmlchar_from_wchar(name);
1634 local = xmlSplitQName2(nameA, &prefix);
1635 heap_free(nameA);
1637 if (!local)
1638 return domelem_get_qualified_item(node, name, NULL, item);
1640 /* try to get namespace uri for supplied qualified name */
1641 ns = xmlSearchNs(node->doc, node, prefix);
1643 xmlFree(prefix);
1645 if (!ns)
1647 xmlFree(local);
1648 if (item) *item = NULL;
1649 return item ? S_FALSE : E_INVALIDARG;
1652 uriW = bstr_from_xmlChar(ns->href);
1653 localW = bstr_from_xmlChar(local);
1654 xmlFree(local);
1656 TRACE("got qualified node %s, uri=%s\n", debugstr_w(localW), debugstr_w(uriW));
1658 hr = domelem_get_qualified_item(node, localW, uriW, item);
1660 SysFreeString(localW);
1661 SysFreeString(uriW);
1663 return hr;
1666 static HRESULT domelem_set_named_item(xmlNodePtr node, IXMLDOMNode *newItem, IXMLDOMNode **namedItem)
1668 xmlNodePtr nodeNew;
1669 xmlnode *ThisNew;
1671 TRACE("(%p)->(%p %p)\n", node, newItem, namedItem );
1673 if(!newItem)
1674 return E_INVALIDARG;
1676 if(namedItem) *namedItem = NULL;
1678 /* Must be an Attribute */
1679 ThisNew = get_node_obj( newItem );
1680 if(!ThisNew) return E_FAIL;
1682 if(ThisNew->node->type != XML_ATTRIBUTE_NODE)
1683 return E_FAIL;
1685 if(!ThisNew->node->parent)
1686 if(xmldoc_remove_orphan(ThisNew->node->doc, ThisNew->node) != S_OK)
1687 WARN("%p is not an orphan of %p\n", ThisNew->node, ThisNew->node->doc);
1689 nodeNew = xmlAddChild(node, ThisNew->node);
1691 if(namedItem)
1692 *namedItem = create_node( nodeNew );
1693 return S_OK;
1696 static HRESULT domelem_remove_qualified_item(xmlNodePtr node, BSTR name, BSTR uri, IXMLDOMNode **item)
1698 xmlChar *nameA, *href;
1699 xmlAttrPtr attr;
1701 TRACE("(%p)->(%s %s %p)\n", node, debugstr_w(name), debugstr_w(uri), item);
1703 if (!name) return E_INVALIDARG;
1705 if (uri && *uri)
1707 href = xmlchar_from_wchar(uri);
1708 if (!href) return E_OUTOFMEMORY;
1710 else
1711 href = NULL;
1713 nameA = xmlchar_from_wchar(name);
1714 if (!nameA)
1716 heap_free(href);
1717 return E_OUTOFMEMORY;
1720 attr = xmlHasNsProp(node, nameA, href);
1722 heap_free(nameA);
1723 heap_free(href);
1725 if (!attr)
1727 if (item) *item = NULL;
1728 return S_FALSE;
1731 if (item)
1733 xmlUnlinkNode( (xmlNodePtr) attr );
1734 xmldoc_add_orphan( attr->doc, (xmlNodePtr) attr );
1735 *item = create_node( (xmlNodePtr) attr );
1737 else
1739 if (xmlRemoveProp(attr) == -1)
1740 ERR("xmlRemoveProp failed\n");
1743 return S_OK;
1746 static HRESULT domelem_remove_named_item(xmlNodePtr node, BSTR name, IXMLDOMNode **item)
1748 xmlChar *nameA, *local, *prefix;
1749 BSTR uriW, localW;
1750 xmlNsPtr ns;
1751 HRESULT hr;
1753 TRACE("(%p)->(%s %p)\n", node, debugstr_w(name), item);
1755 nameA = xmlchar_from_wchar(name);
1756 local = xmlSplitQName2(nameA, &prefix);
1757 heap_free(nameA);
1759 if (!local)
1760 return domelem_remove_qualified_item(node, name, NULL, item);
1762 ns = xmlSearchNs(node->doc, node, prefix);
1764 xmlFree(prefix);
1766 if (!ns)
1768 xmlFree(local);
1769 if (item) *item = NULL;
1770 return item ? S_FALSE : E_INVALIDARG;
1773 uriW = bstr_from_xmlChar(ns->href);
1774 localW = bstr_from_xmlChar(local);
1775 xmlFree(local);
1777 TRACE("removing qualified node %s, uri=%s\n", debugstr_w(localW), debugstr_w(uriW));
1779 hr = domelem_remove_qualified_item(node, localW, uriW, item);
1781 SysFreeString(localW);
1782 SysFreeString(uriW);
1784 return hr;
1787 static HRESULT domelem_get_item(const xmlNodePtr node, LONG index, IXMLDOMNode **item)
1789 xmlNsPtr ns, xmlns;
1790 xmlAttrPtr curr;
1791 LONG attrIndex;
1792 IUnknown *unk;
1793 HRESULT hr;
1795 TRACE("(%p)->(%d %p)\n", node, index, item);
1797 *item = NULL;
1799 if (index < 0)
1800 return S_FALSE;
1802 attrIndex = 0;
1803 curr = node->properties;
1804 if (curr) {
1805 for (; attrIndex < index && curr->next != NULL; attrIndex++)
1806 curr = curr->next;
1808 if (attrIndex == index) {
1809 *item = create_node( (xmlNodePtr) curr );
1810 return S_OK;
1814 if (!node->nsDef)
1815 return S_FALSE;
1817 attrIndex++;
1818 ns = node->nsDef;
1819 for (; attrIndex < index && ns->next != NULL; attrIndex++)
1820 ns = ns->next;
1822 if (attrIndex < index)
1823 return S_FALSE;
1825 xmlns = xmlNewNs(NULL, BAD_CAST "http://www.w3.org/2000/xmlns/", BAD_CAST "xmlns");
1826 if (!xmlns)
1827 return E_OUTOFMEMORY;
1829 curr = xmlNewNsProp(NULL, xmlns, ns->prefix, ns->href);
1830 if (!curr) {
1831 xmlFreeNs(xmlns);
1832 return E_OUTOFMEMORY;
1834 curr->doc = node->doc;
1836 unk = create_attribute((xmlNodePtr)curr, TRUE);
1837 if (!unk) {
1838 xmlFreeNs(xmlns);
1839 xmlFreeProp(curr);
1840 return E_OUTOFMEMORY;
1843 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)item);
1844 IUnknown_Release(unk);
1846 return hr;
1849 static HRESULT domelem_get_length(const xmlNodePtr node, LONG *length)
1851 xmlAttrPtr curr;
1852 LONG attrCount;
1853 xmlNsPtr ns;
1855 TRACE("(%p)->(%p)\n", node, length);
1857 if( !length )
1858 return E_INVALIDARG;
1860 attrCount = 0;
1861 curr = node->properties;
1862 while (curr) {
1863 attrCount++;
1864 curr = curr->next;
1867 ns = node->nsDef;
1868 while (ns) {
1869 attrCount++;
1870 ns = ns->next;
1872 *length = attrCount;
1874 return S_OK;
1877 static HRESULT domelem_next_node(const xmlNodePtr node, LONG *iter, IXMLDOMNode **nextNode)
1879 xmlAttrPtr curr;
1880 LONG i;
1882 TRACE("(%p)->(%d: %p)\n", node, *iter, nextNode);
1884 *nextNode = NULL;
1886 curr = node->properties;
1887 if (curr == NULL)
1888 return S_FALSE;
1890 for (i = 0; i < *iter; i++) {
1891 if (curr->next == NULL)
1892 return S_FALSE;
1893 else
1894 curr = curr->next;
1897 (*iter)++;
1898 *nextNode = create_node((xmlNodePtr)curr);
1900 return S_OK;
1903 static const struct nodemap_funcs domelem_attr_map = {
1904 domelem_get_named_item,
1905 domelem_set_named_item,
1906 domelem_remove_named_item,
1907 domelem_get_item,
1908 domelem_get_length,
1909 domelem_get_qualified_item,
1910 domelem_remove_qualified_item,
1911 domelem_next_node
1914 static const tid_t domelem_iface_tids[] = {
1915 IXMLDOMElement_tid,
1919 static dispex_static_data_t domelem_dispex = {
1920 NULL,
1921 IXMLDOMElement_tid,
1922 NULL,
1923 domelem_iface_tids
1926 IUnknown* create_element( xmlNodePtr element )
1928 domelem *This;
1930 This = heap_alloc( sizeof *This );
1931 if ( !This )
1932 return NULL;
1934 This->IXMLDOMElement_iface.lpVtbl = &domelem_vtbl;
1935 This->ref = 1;
1937 init_xmlnode(&This->node, element, (IXMLDOMNode*)&This->IXMLDOMElement_iface, &domelem_dispex);
1939 return (IUnknown*)&This->IXMLDOMElement_iface;