ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

node.c
Go to the documentation of this file.
00001 /*
00002  *    Node implementation
00003  *
00004  * Copyright 2005 Mike McCormack
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include "config.h"
00022 
00023 #define COBJMACROS
00024 
00025 #include <stdarg.h>
00026 #include <assert.h>
00027 #include "windef.h"
00028 #include "winbase.h"
00029 #include "winuser.h"
00030 #include "winnls.h"
00031 #include "ole2.h"
00032 #include "msxml2.h"
00033 
00034 #include "msxml_private.h"
00035 
00036 #ifdef HAVE_LIBXML2
00037 # include <libxml/HTMLtree.h>
00038 #endif
00039 
00040 #include "wine/debug.h"
00041 
00042 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
00043 
00044 #ifdef HAVE_LIBXML2
00045 
00046 static const WCHAR szBinBase64[]  = {'b','i','n','.','b','a','s','e','6','4',0};
00047 static const WCHAR szString[]     = {'s','t','r','i','n','g',0};
00048 static const WCHAR szNumber[]     = {'n','u','m','b','e','r',0};
00049 static const WCHAR szInt[]        = {'I','n','t',0};
00050 static const WCHAR szFixed[]      = {'F','i','x','e','d','.','1','4','.','4',0};
00051 static const WCHAR szBoolean[]    = {'B','o','o','l','e','a','n',0};
00052 static const WCHAR szDateTime[]   = {'d','a','t','e','T','i','m','e',0};
00053 static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
00054 static const WCHAR szDate[]       = {'D','a','t','e',0};
00055 static const WCHAR szTime[]       = {'T','i','m','e',0};
00056 static const WCHAR szTimeTZ[]     = {'T','i','m','e','.','t','z',0};
00057 static const WCHAR szI1[]         = {'i','1',0};
00058 static const WCHAR szI2[]         = {'i','2',0};
00059 static const WCHAR szI4[]         = {'i','4',0};
00060 static const WCHAR szIU1[]        = {'u','i','1',0};
00061 static const WCHAR szIU2[]        = {'u','i','2',0};
00062 static const WCHAR szIU4[]        = {'u','i','4',0};
00063 static const WCHAR szR4[]         = {'r','4',0};
00064 static const WCHAR szR8[]         = {'r','8',0};
00065 static const WCHAR szFloat[]      = {'f','l','o','a','t',0};
00066 static const WCHAR szUUID[]       = {'u','u','i','d',0};
00067 static const WCHAR szBinHex[]     = {'b','i','n','.','h','e','x',0};
00068 
00069 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
00070 {
00071     xmlnode *This;
00072 
00073     if ( !iface )
00074         return NULL;
00075     This = impl_from_IXMLDOMNode( iface );
00076     if ( !This->node )
00077         return NULL;
00078     if ( type && This->node->type != type )
00079         return NULL;
00080     return This->node;
00081 }
00082 
00083 static HRESULT WINAPI xmlnode_QueryInterface(
00084     IXMLDOMNode *iface,
00085     REFIID riid,
00086     void** ppvObject )
00087 {
00088     xmlnode *This = impl_from_IXMLDOMNode( iface );
00089 
00090     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
00091 
00092     if(This->pUnkOuter)
00093         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject);
00094 
00095     if (IsEqualGUID(riid, &IID_IUnknown)) {
00096         *ppvObject = iface;
00097     }else if (IsEqualGUID( riid, &IID_IDispatch) ||
00098               IsEqualGUID( riid, &IID_IXMLDOMNode)) {
00099         *ppvObject = &This->lpVtbl;
00100     }else  {
00101         FIXME("interface %s not implemented\n", debugstr_guid(riid));
00102         *ppvObject = NULL;
00103         return E_NOINTERFACE;
00104     }
00105 
00106     IUnknown_AddRef( (IUnknown*)*ppvObject );
00107     return S_OK;
00108 }
00109 
00110 static ULONG WINAPI xmlnode_AddRef(
00111     IXMLDOMNode *iface )
00112 {
00113     xmlnode *This = impl_from_IXMLDOMNode( iface );
00114 
00115     if(This->pUnkOuter)
00116         return IUnknown_AddRef(This->pUnkOuter);
00117 
00118     return InterlockedIncrement(&This->ref);
00119 }
00120 
00121 static ULONG WINAPI xmlnode_Release(
00122     IXMLDOMNode *iface )
00123 {
00124     xmlnode *This = impl_from_IXMLDOMNode( iface );
00125     LONG ref;
00126 
00127     if(This->pUnkOuter)
00128         return IUnknown_Release(This->pUnkOuter);
00129 
00130     ref = InterlockedDecrement( &This->ref );
00131     if(!ref) {
00132         destroy_xmlnode(This);
00133         heap_free( This );
00134     }
00135 
00136     return ref;
00137 }
00138 
00139 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
00140     IXMLDOMNode *iface,
00141     UINT* pctinfo )
00142 {
00143     xmlnode *This = impl_from_IXMLDOMNode( iface );
00144 
00145     TRACE("(%p)->(%p)\n", This, pctinfo);
00146 
00147     *pctinfo = 1;
00148 
00149     return S_OK;
00150 }
00151 
00152 static HRESULT WINAPI xmlnode_GetTypeInfo(
00153     IXMLDOMNode *iface,
00154     UINT iTInfo,
00155     LCID lcid,
00156     ITypeInfo** ppTInfo )
00157 {
00158     xmlnode *This = impl_from_IXMLDOMNode( iface );
00159     HRESULT hr;
00160 
00161     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
00162 
00163     hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
00164 
00165     return hr;
00166 }
00167 
00168 static HRESULT WINAPI xmlnode_GetIDsOfNames(
00169     IXMLDOMNode *iface,
00170     REFIID riid,
00171     LPOLESTR* rgszNames,
00172     UINT cNames,
00173     LCID lcid,
00174     DISPID* rgDispId )
00175 {
00176     xmlnode *This = impl_from_IXMLDOMNode( iface );
00177 
00178     ITypeInfo *typeinfo;
00179     HRESULT hr;
00180 
00181     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
00182           lcid, rgDispId);
00183 
00184     if(!rgszNames || cNames == 0 || !rgDispId)
00185         return E_INVALIDARG;
00186 
00187     hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
00188     if(SUCCEEDED(hr))
00189     {
00190         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
00191         ITypeInfo_Release(typeinfo);
00192     }
00193 
00194     return hr;
00195 }
00196 
00197 static HRESULT WINAPI xmlnode_Invoke(
00198     IXMLDOMNode *iface,
00199     DISPID dispIdMember,
00200     REFIID riid,
00201     LCID lcid,
00202     WORD wFlags,
00203     DISPPARAMS* pDispParams,
00204     VARIANT* pVarResult,
00205     EXCEPINFO* pExcepInfo,
00206     UINT* puArgErr )
00207 {
00208     xmlnode *This = impl_from_IXMLDOMNode( iface );
00209     ITypeInfo *typeinfo;
00210     HRESULT hr;
00211 
00212     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
00213           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
00214 
00215     hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
00216     if(SUCCEEDED(hr))
00217     {
00218         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
00219                 pVarResult, pExcepInfo, puArgErr);
00220         ITypeInfo_Release(typeinfo);
00221     }
00222 
00223     return hr;
00224 }
00225 
00226 static HRESULT WINAPI xmlnode_get_nodeName(
00227     IXMLDOMNode *iface,
00228     BSTR* name)
00229 {
00230     xmlnode *This = impl_from_IXMLDOMNode( iface );
00231     const xmlChar *str;
00232 
00233     TRACE("(%p)->(%p)\n", This, name );
00234 
00235     if (!name)
00236         return E_INVALIDARG;
00237 
00238     if ( !This->node )
00239         return E_FAIL;
00240 
00241     switch( This->node->type )
00242     {
00243     case XML_CDATA_SECTION_NODE:
00244         str = (const xmlChar*) "#cdata-section";
00245         break;
00246     case XML_COMMENT_NODE:
00247         str = (const xmlChar*) "#comment";
00248         break;
00249     case XML_DOCUMENT_FRAG_NODE:
00250         str = (const xmlChar*) "#document-fragment";
00251         break;
00252     case XML_TEXT_NODE:
00253         str = (const xmlChar*) "#text";
00254         break;
00255     case XML_DOCUMENT_NODE:
00256         str = (const xmlChar*) "#document";
00257         break;
00258     case XML_ATTRIBUTE_NODE:
00259     case XML_ELEMENT_NODE:
00260     case XML_PI_NODE:
00261         str = This->node->name;
00262         break;
00263     default:
00264         FIXME("nodeName not mapped correctly (%d)\n", This->node->type);
00265         str = This->node->name;
00266         break;
00267     }
00268 
00269     *name = bstr_from_xmlChar( str );
00270     if (!*name)
00271         return S_FALSE;
00272 
00273     return S_OK;
00274 }
00275 
00276 static HRESULT WINAPI xmlnode_get_nodeValue(
00277     IXMLDOMNode *iface,
00278     VARIANT* value)
00279 {
00280     xmlnode *This = impl_from_IXMLDOMNode( iface );
00281     HRESULT r = S_FALSE;
00282 
00283     TRACE("(%p)->(%p)\n", This, value);
00284 
00285     if(!value)
00286         return E_INVALIDARG;
00287 
00288     V_BSTR(value) = NULL;
00289     V_VT(value) = VT_NULL;
00290 
00291     switch ( This->node->type )
00292     {
00293     case XML_CDATA_SECTION_NODE:
00294     case XML_COMMENT_NODE:
00295     case XML_PI_NODE:
00296     case XML_ATTRIBUTE_NODE:
00297       {
00298         xmlChar *content = xmlNodeGetContent(This->node);
00299         V_VT(value) = VT_BSTR;
00300         V_BSTR(value) = bstr_from_xmlChar( content );
00301         xmlFree(content);
00302         r = S_OK;
00303         break;
00304       }
00305     case XML_TEXT_NODE:
00306         V_VT(value) = VT_BSTR;
00307         V_BSTR(value) = bstr_from_xmlChar( This->node->content );
00308         r = S_OK;
00309         break;
00310     case XML_ELEMENT_NODE:
00311     case XML_DOCUMENT_NODE:
00312         /* these seem to return NULL */
00313         break;
00314 
00315     default:
00316         FIXME("node %p type %d\n", This, This->node->type);
00317     }
00318  
00319     TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) );
00320 
00321     return r;
00322 }
00323 
00324 static HRESULT WINAPI xmlnode_put_nodeValue(
00325     IXMLDOMNode *iface,
00326     VARIANT value)
00327 {
00328     xmlnode *This = impl_from_IXMLDOMNode( iface );
00329     HRESULT hr;
00330 
00331     TRACE("%p type(%d)\n", This, This->node->type);
00332 
00333     /* Document, Document Fragment, Document Type, Element,
00334        Entity, Entity Reference, Notation aren't supported. */
00335     switch ( This->node->type )
00336     {
00337     case XML_ATTRIBUTE_NODE:
00338     case XML_CDATA_SECTION_NODE:
00339     case XML_COMMENT_NODE:
00340     case XML_PI_NODE:
00341     case XML_TEXT_NODE:
00342     {
00343         VARIANT string_value;
00344         xmlChar *str;
00345 
00346         VariantInit(&string_value);
00347         hr = VariantChangeType(&string_value, &value, 0, VT_BSTR);
00348         if(FAILED(hr))
00349         {
00350             VariantClear(&string_value);
00351             WARN("Couldn't convert to VT_BSTR\n");
00352             return hr;
00353         }
00354 
00355         str = xmlChar_from_wchar(V_BSTR(&string_value));
00356         VariantClear(&string_value);
00357 
00358         xmlNodeSetContent(This->node, str);
00359         heap_free(str);
00360         hr = S_OK;
00361         break;
00362     }
00363     default:
00364         /* Do nothing for unsupported types. */
00365         hr = E_FAIL;
00366         break;
00367     }
00368 
00369     return hr;
00370 }
00371 
00372 static HRESULT WINAPI xmlnode_get_nodeType(
00373     IXMLDOMNode *iface,
00374     DOMNodeType* type)
00375 {
00376     xmlnode *This = impl_from_IXMLDOMNode( iface );
00377 
00378     TRACE("(%p)->(%p)\n", This, type);
00379 
00380     assert( (int)NODE_ELEMENT  == (int)XML_ELEMENT_NODE );
00381     assert( (int)NODE_NOTATION == (int)XML_NOTATION_NODE );
00382 
00383     *type = This->node->type;
00384 
00385     return S_OK;
00386 }
00387 
00388 static HRESULT get_node(
00389     xmlnode *This,
00390     const char *name,
00391     xmlNodePtr node,
00392     IXMLDOMNode **out )
00393 {
00394     TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
00395 
00396     if ( !out )
00397         return E_INVALIDARG;
00398 
00399     /* if we don't have a doc, use our parent. */
00400     if(node && !node->doc && node->parent)
00401         node->doc = node->parent->doc;
00402 
00403     *out = create_node( node );
00404     if (!*out)
00405         return S_FALSE;
00406     return S_OK;
00407 }
00408 
00409 static HRESULT WINAPI xmlnode_get_parentNode(
00410     IXMLDOMNode *iface,
00411     IXMLDOMNode** parent)
00412 {
00413     xmlnode *This = impl_from_IXMLDOMNode( iface );
00414     return get_node( This, "parent", This->node->parent, parent );
00415 }
00416 
00417 static HRESULT WINAPI xmlnode_get_childNodes(
00418     IXMLDOMNode *iface,
00419     IXMLDOMNodeList** childList)
00420 {
00421     xmlnode *This = impl_from_IXMLDOMNode( iface );
00422 
00423     TRACE("(%p)->(%p)\n", This, childList );
00424 
00425     if ( !childList )
00426         return E_INVALIDARG;
00427 
00428     *childList = create_children_nodelist(This->node);
00429     if (*childList == NULL)
00430         return E_OUTOFMEMORY;
00431 
00432     return S_OK;
00433 }
00434 
00435 static HRESULT WINAPI xmlnode_get_firstChild(
00436     IXMLDOMNode *iface,
00437     IXMLDOMNode** firstChild)
00438 {
00439     xmlnode *This = impl_from_IXMLDOMNode( iface );
00440     TRACE("(%p)->(%p)\n", This, firstChild);
00441     return get_node( This, "firstChild", This->node->children, firstChild );
00442 }
00443 
00444 static HRESULT WINAPI xmlnode_get_lastChild(
00445     IXMLDOMNode *iface,
00446     IXMLDOMNode** lastChild)
00447 {
00448     xmlnode *This = impl_from_IXMLDOMNode( iface );
00449 
00450     TRACE("(%p)->(%p)\n", This, lastChild );
00451 
00452     if (!lastChild)
00453         return E_INVALIDARG;
00454 
00455     switch( This->node->type )
00456     {
00457     /* CDATASection, Comment, PI and Text Nodes do not support lastChild */
00458     case XML_TEXT_NODE:
00459     case XML_CDATA_SECTION_NODE:
00460     case XML_PI_NODE:
00461     case XML_COMMENT_NODE:
00462         *lastChild = NULL;
00463         return S_FALSE;
00464     default:
00465         return get_node( This, "lastChild", This->node->last, lastChild );
00466     }
00467 }
00468 
00469 static HRESULT WINAPI xmlnode_get_previousSibling(
00470     IXMLDOMNode *iface,
00471     IXMLDOMNode** previousSibling)
00472 {
00473     xmlnode *This = impl_from_IXMLDOMNode( iface );
00474 
00475     TRACE("(%p)->(%p)\n", This, previousSibling );
00476 
00477     if (!previousSibling)
00478         return E_INVALIDARG;
00479 
00480     switch( This->node->type )
00481     {
00482     /* Attribute, Document and Document Fragment Nodes do not support previousSibling */
00483     case XML_DOCUMENT_NODE:
00484     case XML_DOCUMENT_FRAG_NODE:
00485     case XML_ATTRIBUTE_NODE:
00486         *previousSibling = NULL;
00487         return S_FALSE;
00488     default:
00489         return get_node( This, "previous", This->node->prev, previousSibling );
00490     }
00491 }
00492 
00493 static HRESULT WINAPI xmlnode_get_nextSibling(
00494     IXMLDOMNode *iface,
00495     IXMLDOMNode** nextSibling)
00496 {
00497     xmlnode *This = impl_from_IXMLDOMNode( iface );
00498 
00499     TRACE("(%p)->(%p)\n", This, nextSibling );
00500 
00501     if (!nextSibling)
00502         return E_INVALIDARG;
00503 
00504     switch( This->node->type )
00505     {
00506     /* Attribute, Document and Document Fragment Nodes do not support nextSibling */
00507     case XML_DOCUMENT_NODE:
00508     case XML_DOCUMENT_FRAG_NODE:
00509     case XML_ATTRIBUTE_NODE:
00510         *nextSibling = NULL;
00511         return S_FALSE;
00512     default:
00513         return get_node( This, "next", This->node->next, nextSibling );
00514     }
00515 }
00516 
00517 static HRESULT WINAPI xmlnode_get_attributes(
00518     IXMLDOMNode *iface,
00519     IXMLDOMNamedNodeMap** attributeMap)
00520 {
00521     xmlnode *This = impl_from_IXMLDOMNode( iface );
00522     TRACE("(%p)->(%p)\n", This, attributeMap);
00523 
00524     if (!attributeMap)
00525         return E_INVALIDARG;
00526 
00527     switch( This->node->type )
00528     {
00529     /* Attribute, CDataSection, Comment, Documents, Documents Fragments,
00530        Entity and Text Nodes does not support get_attributes */
00531     case XML_ATTRIBUTE_NODE:
00532     case XML_CDATA_SECTION_NODE:
00533     case XML_COMMENT_NODE:
00534     case XML_DOCUMENT_NODE:
00535     case XML_DOCUMENT_FRAG_NODE:
00536     case XML_ENTITY_NODE:
00537     case XML_ENTITY_REF_NODE:
00538     case XML_TEXT_NODE:
00539         *attributeMap = NULL;
00540         return S_FALSE;
00541     default:
00542         *attributeMap = create_nodemap( iface );
00543         return S_OK;
00544     }
00545 }
00546 
00547 static HRESULT WINAPI xmlnode_insertBefore(
00548     IXMLDOMNode *iface,
00549     IXMLDOMNode* newChild,
00550     VARIANT refChild,
00551     IXMLDOMNode** outNewChild)
00552 {
00553     xmlnode *This = impl_from_IXMLDOMNode( iface );
00554     xmlNodePtr before_node, new_child_node;
00555     IXMLDOMNode *before = NULL, *new;
00556     HRESULT hr;
00557 
00558     TRACE("(%p)->(%p var %p)\n",This,newChild,outNewChild);
00559 
00560     if (!newChild)
00561         return E_INVALIDARG;
00562 
00563     switch(V_VT(&refChild))
00564     {
00565     case VT_EMPTY:
00566     case VT_NULL:
00567         break;
00568 
00569     case VT_UNKNOWN:
00570         hr = IUnknown_QueryInterface(V_UNKNOWN(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
00571         if(FAILED(hr)) return hr;
00572         break;
00573 
00574     case VT_DISPATCH:
00575         hr = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
00576         if(FAILED(hr)) return hr;
00577         break;
00578 
00579     default:
00580         FIXME("refChild var type %x\n", V_VT(&refChild));
00581         return E_FAIL;
00582     }
00583 
00584     IXMLDOMNode_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID)&new);
00585     new_child_node = impl_from_IXMLDOMNode(new)->node;
00586     TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
00587 
00588     if(!new_child_node->parent)
00589         if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
00590             WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
00591 
00592     if(before)
00593     {
00594         before_node = impl_from_IXMLDOMNode(before)->node;
00595         xmlAddPrevSibling(before_node, new_child_node);
00596         IXMLDOMNode_Release(before);
00597     }
00598     else
00599     {
00600         xmlAddChild(This->node, new_child_node);
00601     }
00602 
00603     IXMLDOMNode_Release(new);
00604     IXMLDOMNode_AddRef(newChild);
00605     if(outNewChild)
00606         *outNewChild = newChild;
00607 
00608     TRACE("ret S_OK\n");
00609     return S_OK;
00610 }
00611 
00612 static HRESULT WINAPI xmlnode_replaceChild(
00613     IXMLDOMNode *iface,
00614     IXMLDOMNode* newChild,
00615     IXMLDOMNode* oldChild,
00616     IXMLDOMNode** outOldChild)
00617 {
00618     xmlnode *This = impl_from_IXMLDOMNode( iface );
00619     xmlNode *old_child_ptr, *new_child_ptr;
00620     xmlDocPtr leaving_doc;
00621     xmlNode *my_ancestor;
00622     IXMLDOMNode *realOldChild;
00623     HRESULT hr;
00624 
00625     TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
00626 
00627     /* Do not believe any documentation telling that newChild == NULL
00628        means removal. It does certainly *not* apply to msxml3! */
00629     if(!newChild || !oldChild)
00630         return E_INVALIDARG;
00631 
00632     if(outOldChild)
00633         *outOldChild = NULL;
00634 
00635     hr = IXMLDOMNode_QueryInterface(oldChild,&IID_IXMLDOMNode,(LPVOID*)&realOldChild);
00636     if(FAILED(hr))
00637         return hr;
00638 
00639     old_child_ptr = impl_from_IXMLDOMNode(realOldChild)->node;
00640     IXMLDOMNode_Release(realOldChild);
00641     if(old_child_ptr->parent != This->node)
00642     {
00643         WARN("childNode %p is not a child of %p\n", oldChild, iface);
00644         return E_INVALIDARG;
00645     }
00646 
00647     new_child_ptr = impl_from_IXMLDOMNode(newChild)->node;
00648     my_ancestor = This->node;
00649     while(my_ancestor)
00650     {
00651         if(my_ancestor == new_child_ptr)
00652         {
00653             WARN("tried to create loop\n");
00654             return E_FAIL;
00655         }
00656         my_ancestor = my_ancestor->parent;
00657     }
00658 
00659     if(!new_child_ptr->parent)
00660         if(xmldoc_remove_orphan(new_child_ptr->doc, new_child_ptr) != S_OK)
00661             WARN("%p is not an orphan of %p\n", new_child_ptr, new_child_ptr->doc);
00662 
00663     leaving_doc = new_child_ptr->doc;
00664     xmldoc_add_ref(old_child_ptr->doc);
00665     xmlReplaceNode(old_child_ptr, new_child_ptr);
00666     xmldoc_release(leaving_doc);
00667 
00668     xmldoc_add_orphan(old_child_ptr->doc, old_child_ptr);
00669 
00670     if(outOldChild)
00671     {
00672         IXMLDOMNode_AddRef(oldChild);
00673         *outOldChild = oldChild;
00674     }
00675 
00676     return S_OK;
00677 }
00678 
00679 static HRESULT WINAPI xmlnode_removeChild(
00680     IXMLDOMNode *iface,
00681     IXMLDOMNode* childNode,
00682     IXMLDOMNode** oldChild)
00683 {
00684     xmlnode *This = impl_from_IXMLDOMNode( iface );
00685     xmlNode *child_node_ptr;
00686     HRESULT hr;
00687     IXMLDOMNode *child;
00688 
00689     TRACE("(%p)->(%p %p)\n", This, childNode, oldChild);
00690 
00691     if(!childNode) return E_INVALIDARG;
00692 
00693     if(oldChild)
00694         *oldChild = NULL;
00695 
00696     hr = IXMLDOMNode_QueryInterface(childNode, &IID_IXMLDOMNode, (LPVOID)&child);
00697     if(FAILED(hr))
00698         return hr;
00699 
00700     child_node_ptr = impl_from_IXMLDOMNode(child)->node;
00701     if(child_node_ptr->parent != This->node)
00702     {
00703         WARN("childNode %p is not a child of %p\n", childNode, iface);
00704         IXMLDOMNode_Release(child);
00705         return E_INVALIDARG;
00706     }
00707 
00708     xmlUnlinkNode(child_node_ptr);
00709 
00710     IXMLDOMNode_Release(child);
00711 
00712     if(oldChild)
00713     {
00714         IXMLDOMNode_AddRef(childNode);
00715         *oldChild = childNode;
00716     }
00717 
00718     return S_OK;
00719 }
00720 
00721 static HRESULT WINAPI xmlnode_appendChild(
00722     IXMLDOMNode *iface,
00723     IXMLDOMNode* newChild,
00724     IXMLDOMNode** outNewChild)
00725 {
00726     xmlnode *This = impl_from_IXMLDOMNode( iface );
00727     DOMNodeType type;
00728     VARIANT var;
00729     HRESULT hr;
00730 
00731     TRACE("(%p)->(%p %p)\n", This, newChild, outNewChild);
00732 
00733     hr = IXMLDOMNode_get_nodeType(newChild, &type);
00734     if(FAILED(hr) || type == NODE_ATTRIBUTE) {
00735         if(outNewChild) *outNewChild = NULL;
00736         return E_FAIL;
00737     }
00738 
00739     VariantInit(&var);
00740     return IXMLDOMNode_insertBefore(iface, newChild, var, outNewChild);
00741 }
00742 
00743 static HRESULT WINAPI xmlnode_hasChildNodes(
00744     IXMLDOMNode *iface,
00745     VARIANT_BOOL* hasChild)
00746 {
00747     xmlnode *This = impl_from_IXMLDOMNode( iface );
00748 
00749     TRACE("(%p)->(%p)\n", This, hasChild);
00750 
00751     if (!hasChild)
00752         return E_INVALIDARG;
00753     if (!This->node->children)
00754     {
00755         *hasChild = VARIANT_FALSE;
00756         return S_FALSE;
00757     }
00758 
00759     *hasChild = VARIANT_TRUE;
00760     return S_OK;
00761 }
00762 
00763 static HRESULT WINAPI xmlnode_get_ownerDocument(
00764     IXMLDOMNode *iface,
00765     IXMLDOMDocument** DOMDocument)
00766 {
00767     xmlnode *This = impl_from_IXMLDOMNode( iface );
00768 
00769     TRACE("(%p)->(%p)\n", This, DOMDocument);
00770 
00771     return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument2**)DOMDocument);
00772 }
00773 
00774 static HRESULT WINAPI xmlnode_cloneNode(
00775     IXMLDOMNode *iface,
00776     VARIANT_BOOL deep,
00777     IXMLDOMNode** cloneRoot)
00778 {
00779     xmlnode *This = impl_from_IXMLDOMNode( iface );
00780     xmlNodePtr pClone = NULL;
00781     IXMLDOMNode *pNode = NULL;
00782 
00783     TRACE("(%p)->(%d %p)\n", This, deep, cloneRoot);
00784 
00785     if(!cloneRoot)
00786         return E_INVALIDARG;
00787 
00788     pClone = xmlCopyNode(This->node, deep ? 1 : 2);
00789     if(pClone)
00790     {
00791         pClone->doc = This->node->doc;
00792         xmldoc_add_orphan(pClone->doc, pClone);
00793 
00794         pNode = create_node(pClone);
00795         if(!pNode)
00796         {
00797             ERR("Copy failed\n");
00798             return E_FAIL;
00799         }
00800 
00801         *cloneRoot = pNode;
00802     }
00803     else
00804     {
00805         ERR("Copy failed\n");
00806         return E_FAIL;
00807     }
00808 
00809     return S_OK;
00810 }
00811 
00812 static HRESULT WINAPI xmlnode_get_nodeTypeString(
00813     IXMLDOMNode *iface,
00814     BSTR* xmlnodeType)
00815 {
00816     xmlnode *This = impl_from_IXMLDOMNode( iface );
00817     const xmlChar *str;
00818 
00819     TRACE("(%p)->(%p)\n", This, xmlnodeType );
00820 
00821     if (!xmlnodeType)
00822         return E_INVALIDARG;
00823 
00824     if ( !This->node )
00825         return E_FAIL;
00826 
00827     switch( This->node->type )
00828     {
00829     case XML_ATTRIBUTE_NODE:
00830         str = (const xmlChar*) "attribute";
00831         break;
00832     case XML_CDATA_SECTION_NODE:
00833         str = (const xmlChar*) "cdatasection";
00834         break;
00835     case XML_COMMENT_NODE:
00836         str = (const xmlChar*) "comment";
00837         break;
00838     case XML_DOCUMENT_NODE:
00839         str = (const xmlChar*) "document";
00840         break;
00841     case XML_DOCUMENT_FRAG_NODE:
00842         str = (const xmlChar*) "documentfragment";
00843         break;
00844     case XML_ELEMENT_NODE:
00845         str = (const xmlChar*) "element";
00846         break;
00847     case XML_ENTITY_NODE:
00848         str = (const xmlChar*) "entity";
00849         break;
00850     case XML_ENTITY_REF_NODE:
00851         str = (const xmlChar*) "entityreference";
00852         break;
00853     case XML_NOTATION_NODE:
00854         str = (const xmlChar*) "notation";
00855         break;
00856     case XML_PI_NODE:
00857         str = (const xmlChar*) "processinginstruction";
00858         break;
00859     case XML_TEXT_NODE:
00860         str = (const xmlChar*) "text";
00861         break;
00862     default:
00863         FIXME("Unknown node type (%d)\n", This->node->type);
00864         str = This->node->name;
00865         break;
00866     }
00867 
00868     *xmlnodeType = bstr_from_xmlChar( str );
00869     if (!*xmlnodeType)
00870         return S_FALSE;
00871 
00872     return S_OK;
00873 }
00874 
00875 static HRESULT WINAPI xmlnode_get_text(
00876     IXMLDOMNode *iface,
00877     BSTR* text)
00878 {
00879     xmlnode *This = impl_from_IXMLDOMNode( iface );
00880     BSTR str = NULL;
00881     xmlChar *pContent;
00882 
00883     TRACE("(%p, type %d)->(%p)\n", This, This->node->type, text);
00884 
00885     if ( !text )
00886         return E_INVALIDARG;
00887 
00888     pContent = xmlNodeGetContent((xmlNodePtr)This->node);
00889     if(pContent)
00890     {
00891         str = bstr_from_xmlChar(pContent);
00892         xmlFree(pContent);
00893     }
00894 
00895     /* Always return a string. */
00896     if (!str) str = SysAllocStringLen( NULL, 0 );
00897 
00898     TRACE("%p %s\n", This, debugstr_w(str) );
00899     *text = str;
00900  
00901     return S_OK;
00902 }
00903 
00904 static HRESULT WINAPI xmlnode_put_text(
00905     IXMLDOMNode *iface,
00906     BSTR text)
00907 {
00908     xmlnode *This = impl_from_IXMLDOMNode( iface );
00909     xmlChar *str, *str2;
00910 
00911     TRACE("(%p)->(%s)\n", This, debugstr_w(text));
00912 
00913     switch(This->node->type)
00914     {
00915     case XML_DOCUMENT_NODE:
00916         return E_FAIL;
00917     default:
00918         break;
00919     }
00920 
00921     str = xmlChar_from_wchar(text);
00922 
00923     /* Escape the string. */
00924     str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
00925     heap_free(str);
00926 
00927     xmlNodeSetContent(This->node, str2);
00928     xmlFree(str2);
00929 
00930     return S_OK;
00931 }
00932 
00933 static HRESULT WINAPI xmlnode_get_specified(
00934     IXMLDOMNode *iface,
00935     VARIANT_BOOL* isSpecified)
00936 {
00937     xmlnode *This = impl_from_IXMLDOMNode( iface );
00938     FIXME("(%p)->(%p) stub!\n", This, isSpecified);
00939     *isSpecified = VARIANT_TRUE;
00940     return S_OK;
00941 }
00942 
00943 static HRESULT WINAPI xmlnode_get_definition(
00944     IXMLDOMNode *iface,
00945     IXMLDOMNode** definitionNode)
00946 {
00947     xmlnode *This = impl_from_IXMLDOMNode( iface );
00948     FIXME("(%p)->(%p)\n", This, definitionNode);
00949     return E_NOTIMPL;
00950 }
00951 
00952 static inline BYTE hex_to_byte(xmlChar c)
00953 {
00954     if(c <= '9') return c-'0';
00955     if(c <= 'F') return c-'A'+10;
00956     return c-'a'+10;
00957 }
00958 
00959 static inline BYTE base64_to_byte(xmlChar c)
00960 {
00961     if(c == '+') return 62;
00962     if(c == '/') return 63;
00963     if(c <= '9') return c-'0'+52;
00964     if(c <= 'Z') return c-'A';
00965     return c-'a'+26;
00966 }
00967 
00968 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
00969 {
00970     if(!type || !lstrcmpiW(type, szString) ||
00971             !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
00972     {
00973         V_VT(v) = VT_BSTR;
00974         V_BSTR(v) = bstr_from_xmlChar(str);
00975 
00976         if(!V_BSTR(v))
00977             return E_OUTOFMEMORY;
00978     }
00979     else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
00980             !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
00981             !lstrcmpiW(type, szTimeTZ))
00982     {
00983         VARIANT src;
00984         WCHAR *p, *e;
00985         SYSTEMTIME st;
00986         DOUBLE date = 0.0;
00987 
00988         st.wYear = 1899;
00989         st.wMonth = 12;
00990         st.wDay = 30;
00991         st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
00992 
00993         V_VT(&src) = VT_BSTR;
00994         V_BSTR(&src) = bstr_from_xmlChar(str);
00995 
00996         if(!V_BSTR(&src))
00997             return E_OUTOFMEMORY;
00998 
00999         p = V_BSTR(&src);
01000         e = p + SysStringLen(V_BSTR(&src));
01001 
01002         if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
01003         {
01004             st.wYear = atoiW(p);
01005             st.wMonth = atoiW(p+5);
01006             st.wDay = atoiW(p+8);
01007             p += 10;
01008 
01009             if(*p == 'T') p++;
01010         }
01011 
01012         if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
01013         {
01014             st.wHour = atoiW(p);
01015             st.wMinute = atoiW(p+3);
01016             st.wSecond = atoiW(p+6);
01017             p += 8;
01018 
01019             if(*p == '.')
01020             {
01021                 p++;
01022                 while(isdigitW(*p)) p++;
01023             }
01024         }
01025 
01026         SystemTimeToVariantTime(&st, &date);
01027         V_VT(v) = VT_DATE;
01028         V_DATE(v) = date;
01029 
01030         if(*p == '+') /* parse timezone offset (+hh:mm) */
01031             V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
01032         else if(*p == '-') /* parse timezone offset (-hh:mm) */
01033             V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
01034 
01035         VariantClear(&src);
01036     }
01037     else if(!lstrcmpiW(type, szBinHex))
01038     {
01039         SAFEARRAYBOUND sab;
01040         int i, len;
01041 
01042         len = xmlStrlen(str)/2;
01043         sab.lLbound = 0;
01044         sab.cElements = len;
01045 
01046         V_VT(v) = (VT_ARRAY|VT_UI1);
01047         V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
01048 
01049         if(!V_ARRAY(v))
01050             return E_OUTOFMEMORY;
01051 
01052         for(i=0; i<len; i++)
01053             ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
01054                 + hex_to_byte(str[2*i+1]);
01055     }
01056     else if(!lstrcmpiW(type, szBinBase64))
01057     {
01058         SAFEARRAYBOUND sab;
01059         int i, len;
01060 
01061         len  = xmlStrlen(str);
01062         if(str[len-2] == '=') i = 2;
01063         else if(str[len-1] == '=') i = 1;
01064         else i = 0;
01065 
01066         sab.lLbound = 0;
01067         sab.cElements = len/4*3-i;
01068 
01069         V_VT(v) = (VT_ARRAY|VT_UI1);
01070         V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
01071 
01072         if(!V_ARRAY(v))
01073             return E_OUTOFMEMORY;
01074 
01075         for(i=0; i<len/4; i++)
01076         {
01077             ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
01078                 + (base64_to_byte(str[4*i+1])>>4);
01079             if(3*i+1 < sab.cElements)
01080                 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
01081                     + (base64_to_byte(str[4*i+2])>>2);
01082             if(3*i+2 < sab.cElements)
01083                 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
01084                     + base64_to_byte(str[4*i+3]);
01085         }
01086     }
01087     else
01088     {
01089         VARIANT src;
01090         HRESULT hres;
01091 
01092         if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
01093             V_VT(v) = VT_I4;
01094         else if(!lstrcmpiW(type, szFixed))
01095             V_VT(v) = VT_CY;
01096         else if(!lstrcmpiW(type, szBoolean))
01097             V_VT(v) = VT_BOOL;
01098         else if(!lstrcmpiW(type, szI1))
01099             V_VT(v) = VT_I1;
01100         else if(!lstrcmpiW(type, szI2))
01101             V_VT(v) = VT_I2;
01102         else if(!lstrcmpiW(type, szIU1))
01103             V_VT(v) = VT_UI1;
01104         else if(!lstrcmpiW(type, szIU2))
01105             V_VT(v) = VT_UI2;
01106         else if(!lstrcmpiW(type, szIU4))
01107             V_VT(v) = VT_UI4;
01108         else if(!lstrcmpiW(type, szR4))
01109             V_VT(v) = VT_R4;
01110         else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
01111             V_VT(v) = VT_R8;
01112         else
01113         {
01114             FIXME("Type handling not yet implemented\n");
01115             V_VT(v) = VT_BSTR;
01116         }
01117 
01118         V_VT(&src) = VT_BSTR;
01119         V_BSTR(&src) = bstr_from_xmlChar(str);
01120 
01121         if(!V_BSTR(&src))
01122             return E_OUTOFMEMORY;
01123 
01124         hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
01125                         LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
01126         VariantClear(&src);
01127         return hres;
01128     }
01129 
01130     return S_OK;
01131 }
01132 
01133 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
01134     IXMLDOMNode *iface,
01135     VARIANT* typedValue)
01136 {
01137     xmlnode *This = impl_from_IXMLDOMNode( iface );
01138     VARIANT type;
01139     xmlChar *content;
01140     HRESULT hres = S_FALSE;
01141 
01142     TRACE("(%p)->(%p)\n", This, typedValue);
01143 
01144     if(!typedValue)
01145         return E_INVALIDARG;
01146 
01147     V_VT(typedValue) = VT_NULL;
01148 
01149     if(This->node->type == XML_ELEMENT_NODE ||
01150             This->node->type == XML_TEXT_NODE ||
01151             This->node->type == XML_ENTITY_REF_NODE)
01152         hres = IXMLDOMNode_get_dataType(iface, &type);
01153 
01154     if(hres != S_OK && This->node->type != XML_ELEMENT_NODE)
01155         return IXMLDOMNode_get_nodeValue(iface, typedValue);
01156 
01157     content = xmlNodeGetContent(This->node);
01158     hres = VARIANT_from_xmlChar(content, typedValue,
01159             hres==S_OK ? V_BSTR(&type) : NULL);
01160     xmlFree(content);
01161     VariantClear(&type);
01162 
01163     return hres;
01164 }
01165 
01166 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
01167     IXMLDOMNode *iface,
01168     VARIANT typedValue)
01169 {
01170     xmlnode *This = impl_from_IXMLDOMNode( iface );
01171     FIXME("%p\n", This);
01172     return E_NOTIMPL;
01173 }
01174 
01175 static HRESULT WINAPI xmlnode_get_dataType(
01176     IXMLDOMNode *iface,
01177     VARIANT* dataTypeName)
01178 {
01179     xmlnode *This = impl_from_IXMLDOMNode( iface );
01180     xmlChar *pVal;
01181 
01182     TRACE("(%p)->(%p)\n", This, dataTypeName);
01183 
01184     if(!dataTypeName)
01185         return E_INVALIDARG;
01186 
01187     /* Attribute, CDATA Section, Comment, Document, Document Fragment,
01188         Entity, Notation, PI, and Text Node are non-typed. */
01189     V_BSTR(dataTypeName) = NULL;
01190     V_VT(dataTypeName) = VT_NULL;
01191 
01192     switch ( This->node->type )
01193     {
01194     case XML_ELEMENT_NODE:
01195         pVal = xmlGetNsProp(This->node, (const xmlChar*)"dt",
01196                             (const xmlChar*)"urn:schemas-microsoft-com:datatypes");
01197         if (pVal)
01198         {
01199             V_VT(dataTypeName) = VT_BSTR;
01200             V_BSTR(dataTypeName) = bstr_from_xmlChar( pVal );
01201             xmlFree(pVal);
01202         }
01203         break;
01204     case XML_ENTITY_REF_NODE:
01205         FIXME("XML_ENTITY_REF_NODE should return a valid value.\n");
01206         break;
01207     default:
01208         TRACE("Type %d returning NULL\n", This->node->type);
01209     }
01210 
01211     /* non-typed nodes return S_FALSE */
01212     if(V_VT(dataTypeName) == VT_NULL)
01213     {
01214         return S_FALSE;
01215     }
01216 
01217     return S_OK;
01218 }
01219 
01220 static HRESULT WINAPI xmlnode_put_dataType(
01221     IXMLDOMNode *iface,
01222     BSTR dataTypeName)
01223 {
01224     xmlnode *This = impl_from_IXMLDOMNode( iface );
01225     HRESULT hr = E_FAIL;
01226 
01227     TRACE("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
01228 
01229     if(dataTypeName == NULL)
01230         return E_INVALIDARG;
01231 
01232     /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
01233        This applies to changing types (string->bool) or setting a new one
01234      */
01235     FIXME("Need to Validate the data before allowing a type to be set.\n");
01236 
01237     /* Check all supported types. */
01238     if(lstrcmpiW(dataTypeName,szString) == 0  ||
01239        lstrcmpiW(dataTypeName,szNumber) == 0  ||
01240        lstrcmpiW(dataTypeName,szUUID) == 0    ||
01241        lstrcmpiW(dataTypeName,szInt) == 0     ||
01242        lstrcmpiW(dataTypeName,szI4) == 0      ||
01243        lstrcmpiW(dataTypeName,szFixed) == 0   ||
01244        lstrcmpiW(dataTypeName,szBoolean) == 0 ||
01245        lstrcmpiW(dataTypeName,szDateTime) == 0 ||
01246        lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
01247        lstrcmpiW(dataTypeName,szDate) == 0    ||
01248        lstrcmpiW(dataTypeName,szTime) == 0    ||
01249        lstrcmpiW(dataTypeName,szTimeTZ) == 0  ||
01250        lstrcmpiW(dataTypeName,szI1) == 0      ||
01251        lstrcmpiW(dataTypeName,szI2) == 0      ||
01252        lstrcmpiW(dataTypeName,szIU1) == 0     ||
01253        lstrcmpiW(dataTypeName,szIU2) == 0     ||
01254        lstrcmpiW(dataTypeName,szIU4) == 0     ||
01255        lstrcmpiW(dataTypeName,szR4) == 0      ||
01256        lstrcmpiW(dataTypeName,szR8) == 0      ||
01257        lstrcmpiW(dataTypeName,szFloat) == 0   ||
01258        lstrcmpiW(dataTypeName,szBinHex) == 0  ||
01259        lstrcmpiW(dataTypeName,szBinBase64) == 0)
01260     {
01261         xmlNsPtr pNS = NULL;
01262         xmlAttrPtr pAttr = NULL;
01263         xmlChar* str = xmlChar_from_wchar(dataTypeName);
01264 
01265         pAttr = xmlHasNsProp(This->node, (const xmlChar*)"dt",
01266                             (const xmlChar*)"urn:schemas-microsoft-com:datatypes");
01267         if (pAttr)
01268         {
01269             pAttr = xmlSetNsProp(This->node, pAttr->ns, (const xmlChar*)"dt", str);
01270 
01271             hr = S_OK;
01272         }
01273         else
01274         {
01275             pNS = xmlNewNs(This->node, (const xmlChar*)"urn:schemas-microsoft-com:datatypes", (const xmlChar*)"dt");
01276             if(pNS)
01277             {
01278                 pAttr = xmlNewNsProp(This->node, pNS, (const xmlChar*)"dt", str);
01279                 if(pAttr)
01280                 {
01281                     xmlAddChild(This->node, (xmlNodePtr)pAttr);
01282 
01283                     hr = S_OK;
01284                 }
01285                 else
01286                     ERR("Failed to create Attribute\n");
01287             }
01288             else
01289                 ERR("Failed to Create Namepsace\n");
01290         }
01291         heap_free( str );
01292     }
01293 
01294     return hr;
01295 }
01296 
01297 static BSTR EnsureCorrectEOL(BSTR sInput)
01298 {
01299     int nNum = 0;
01300     BSTR sNew;
01301     int nLen;
01302     int i;
01303 
01304     nLen = lstrlenW(sInput);
01305     /* Count line endings */
01306     for(i=0; i < nLen; i++)
01307     {
01308         if(sInput[i] == '\n')
01309             nNum++;
01310     }
01311 
01312     TRACE("len=%d, num=%d\n", nLen, nNum);
01313 
01314     /* Add linefeed as needed */
01315     if(nNum > 0)
01316     {
01317         int nPlace = 0;
01318         sNew = SysAllocStringLen(NULL, nLen + nNum+1);
01319         for(i=0; i < nLen; i++)
01320         {
01321             if(sInput[i] == '\n')
01322             {
01323                 sNew[i+nPlace] = '\r';
01324                 nPlace++;
01325             }
01326             sNew[i+nPlace] = sInput[i];
01327         }
01328 
01329         SysFreeString(sInput);
01330     }
01331     else
01332     {
01333         sNew = sInput;
01334     }
01335 
01336     TRACE("len %d\n", lstrlenW(sNew));
01337 
01338     return sNew;
01339 }
01340 
01341 /* Removes encoding information and last character (nullbyte) */
01342 static BSTR EnsureNoEncoding(BSTR sInput)
01343 {
01344     static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
01345     BSTR sNew;
01346     WCHAR *pBeg, *pEnd;
01347 
01348     pBeg = sInput;
01349     while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
01350         pBeg++;
01351 
01352     if(*pBeg == '\n')
01353     {
01354         SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
01355         return sInput;
01356     }
01357     pBeg--;
01358 
01359     pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
01360     while(*pEnd != '\"') pEnd++;
01361     pEnd++;
01362 
01363     sNew = SysAllocStringLen(NULL,
01364             pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
01365     memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
01366     memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
01367 
01368     SysFreeString(sInput);
01369     return sNew;
01370 }
01371 
01372 /*
01373  * We are trying to replicate the same behaviour as msxml by converting
01374  * line endings to \r\n and using indents as \t. The problem is that msxml
01375  * only formats nodes that have a line ending. Using libxml we cannot
01376  * reproduce behaviour exactly.
01377  *
01378  */
01379 static HRESULT WINAPI xmlnode_get_xml(
01380     IXMLDOMNode *iface,
01381     BSTR* xmlString)
01382 {
01383     xmlnode *This = impl_from_IXMLDOMNode( iface );
01384     xmlBufferPtr pXmlBuf;
01385     xmlNodePtr xmldecl;
01386     int nSize;
01387 
01388     TRACE("(%p %d)->(%p)\n", This, This->node->type, xmlString);
01389 
01390     if(!xmlString)
01391         return E_INVALIDARG;
01392 
01393     *xmlString = NULL;
01394 
01395     xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
01396 
01397     pXmlBuf = xmlBufferCreate();
01398     if(pXmlBuf)
01399     {
01400         nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 1);
01401         if(nSize > 0)
01402         {
01403             const xmlChar *pContent;
01404             BSTR bstrContent;
01405 
01406             /* Attribute Nodes return a space in front of their name */
01407             pContent = xmlBufferContent(pXmlBuf);
01408             if( ((const char*)pContent)[0] == ' ')
01409                 bstrContent = bstr_from_xmlChar(pContent+1);
01410             else
01411                 bstrContent = bstr_from_xmlChar(pContent);
01412 
01413             switch(This->node->type)
01414             {
01415                 case XML_ELEMENT_NODE:
01416                     *xmlString = EnsureCorrectEOL(bstrContent);
01417                     break;
01418                 case XML_DOCUMENT_NODE:
01419                     *xmlString = EnsureCorrectEOL(bstrContent);
01420                     *xmlString = EnsureNoEncoding(*xmlString);
01421                     break;
01422                 default:
01423                     *xmlString = bstrContent;
01424             }
01425         }
01426 
01427         xmlBufferFree(pXmlBuf);
01428     }
01429 
01430     xmldoc_link_xmldecl( This->node->doc, xmldecl );
01431 
01432     /* Always returns a string. */
01433     if(*xmlString == NULL)  *xmlString = SysAllocStringLen( NULL, 0 );
01434 
01435     return S_OK;
01436 }
01437 
01438 static HRESULT WINAPI xmlnode_transformNode(
01439     IXMLDOMNode *iface,
01440     IXMLDOMNode* styleSheet,
01441     BSTR* xmlString)
01442 {
01443 #ifdef SONAME_LIBXSLT
01444     xmlnode *This = impl_from_IXMLDOMNode( iface );
01445     xmlnode *pStyleSheet = NULL;
01446     xsltStylesheetPtr xsltSS = NULL;
01447     xmlDocPtr result = NULL;
01448     IXMLDOMNode *ssNew;
01449 
01450     TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
01451 
01452     if (!libxslt_handle)
01453         return E_NOTIMPL;
01454     if(!styleSheet || !xmlString)
01455         return E_INVALIDARG;
01456 
01457     *xmlString = NULL;
01458 
01459     if(IXMLDOMNode_QueryInterface(styleSheet, &IID_IXMLDOMNode, (LPVOID)&ssNew) == S_OK)
01460     {
01461         pStyleSheet = impl_from_IXMLDOMNode( ssNew );
01462 
01463         xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
01464         if(xsltSS)
01465         {
01466             result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
01467             if(result)
01468             {
01469                 const xmlChar *pContent;
01470 
01471                 if(result->type == XML_HTML_DOCUMENT_NODE)
01472                 {
01473                     xmlOutputBufferPtr  pOutput = xmlAllocOutputBuffer(NULL);
01474                     if(pOutput)
01475                     {
01476                         htmlDocContentDumpOutput(pOutput, result->doc, NULL);
01477                         pContent = xmlBufferContent(pOutput->buffer);
01478                         *xmlString = bstr_from_xmlChar(pContent);
01479                         xmlOutputBufferClose(pOutput);
01480                     }
01481                 }
01482                 else
01483                 {
01484                     xmlBufferPtr pXmlBuf;
01485                     int nSize;
01486 
01487                     pXmlBuf = xmlBufferCreate();
01488                     if(pXmlBuf)
01489                     {
01490                         nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
01491                         if(nSize > 0)
01492                         {
01493                             pContent = xmlBufferContent(pXmlBuf);
01494                             *xmlString = bstr_from_xmlChar(pContent);
01495                         }
01496                         xmlBufferFree(pXmlBuf);
01497                     }
01498                 }
01499                 xmlFreeDoc(result);
01500             }
01501             /* libxslt "helpfully" frees the XML document the stylesheet was
01502                generated from, too */
01503             xsltSS->doc = NULL;
01504             pxsltFreeStylesheet(xsltSS);
01505         }
01506 
01507         IXMLDOMNode_Release(ssNew);
01508     }
01509 
01510     if(*xmlString == NULL)
01511         *xmlString = SysAllocStringLen(NULL, 0);
01512 
01513     return S_OK;
01514 #else
01515     FIXME("libxslt headers were not found at compile time\n");
01516     return E_NOTIMPL;
01517 #endif
01518 }
01519 
01520 static HRESULT WINAPI xmlnode_selectNodes(
01521     IXMLDOMNode *iface,
01522     BSTR queryString,
01523     IXMLDOMNodeList** resultList)
01524 {
01525     xmlnode *This = impl_from_IXMLDOMNode( iface );
01526 
01527     TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
01528 
01529     return queryresult_create( This->node, queryString, resultList );
01530 }
01531 
01532 static HRESULT WINAPI xmlnode_selectSingleNode(
01533     IXMLDOMNode *iface,
01534     BSTR queryString,
01535     IXMLDOMNode** resultNode)
01536 {
01537     xmlnode *This = impl_from_IXMLDOMNode( iface );
01538     IXMLDOMNodeList *list;
01539     HRESULT r;
01540 
01541     TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
01542 
01543     *resultNode = NULL;
01544     r = IXMLDOMNode_selectNodes(iface, queryString, &list);
01545     if(r == S_OK)
01546     {
01547         r = IXMLDOMNodeList_nextNode(list, resultNode);
01548         IXMLDOMNodeList_Release(list);
01549     }
01550     return r;
01551 }
01552 
01553 static HRESULT WINAPI xmlnode_get_parsed(
01554     IXMLDOMNode *iface,
01555     VARIANT_BOOL* isParsed)
01556 {
01557     xmlnode *This = impl_from_IXMLDOMNode( iface );
01558     FIXME("(%p)->(%p) stub!\n", This, isParsed);
01559     *isParsed = VARIANT_TRUE;
01560     return S_OK;
01561 }
01562 
01563 static HRESULT WINAPI xmlnode_get_namespaceURI(
01564     IXMLDOMNode *iface,
01565     BSTR* namespaceURI)
01566 {
01567     xmlnode *This = impl_from_IXMLDOMNode( iface );
01568     HRESULT hr = S_FALSE;
01569     xmlNsPtr *pNSList;
01570 
01571     TRACE("(%p)->(%p)\n", This, namespaceURI );
01572 
01573     if(!namespaceURI)
01574         return E_INVALIDARG;
01575 
01576     *namespaceURI = NULL;
01577 
01578     pNSList = xmlGetNsList(This->node->doc, This->node);
01579     if(pNSList)
01580     {
01581         *namespaceURI = bstr_from_xmlChar( pNSList[0]->href );
01582 
01583         xmlFree( pNSList );
01584         hr = S_OK;
01585     }
01586 
01587     return hr;
01588 }
01589 
01590 static HRESULT WINAPI xmlnode_get_prefix(
01591     IXMLDOMNode *iface,
01592     BSTR* prefixString)
01593 {
01594     xmlnode *This = impl_from_IXMLDOMNode( iface );
01595     HRESULT hr = S_FALSE;
01596     xmlNsPtr *pNSList;
01597 
01598     TRACE("(%p)->(%p)\n", This, prefixString );
01599 
01600     if(!prefixString)
01601         return E_INVALIDARG;
01602 
01603     *prefixString = NULL;
01604 
01605     pNSList = xmlGetNsList(This->node->doc, This->node);
01606     if(pNSList)
01607     {
01608         *prefixString = bstr_from_xmlChar( pNSList[0]->prefix );
01609 
01610         xmlFree(pNSList);
01611         hr = S_OK;
01612     }
01613 
01614     return hr;
01615 }
01616 
01617 static HRESULT WINAPI xmlnode_get_baseName(
01618     IXMLDOMNode *iface,
01619     BSTR* nameString)
01620 {
01621     xmlnode *This = impl_from_IXMLDOMNode( iface );
01622     BSTR str = NULL;
01623     HRESULT r = S_FALSE;
01624 
01625     TRACE("(%p)->(%p)\n", This, nameString );
01626 
01627     if ( !nameString )
01628         return E_INVALIDARG;
01629 
01630     switch ( This->node->type )
01631     {
01632     case XML_ELEMENT_NODE:
01633     case XML_ATTRIBUTE_NODE:
01634     case XML_PI_NODE:
01635         str = bstr_from_xmlChar( This->node->name );
01636         r = S_OK;
01637         break;
01638     case XML_TEXT_NODE:
01639     case XML_COMMENT_NODE:
01640     case XML_DOCUMENT_NODE:
01641         break;
01642     default:
01643         ERR("Unhandled type %d\n", This->node->type );
01644         break;
01645     }
01646 
01647     TRACE("returning %08x str = %s\n", r, debugstr_w( str ) );
01648 
01649     *nameString = str;
01650     return r;
01651 }
01652 
01653 static HRESULT WINAPI xmlnode_transformNodeToObject(
01654     IXMLDOMNode *iface,
01655     IXMLDOMNode* stylesheet,
01656     VARIANT outputObject)
01657 {
01658     xmlnode *This = impl_from_IXMLDOMNode( iface );
01659     FIXME("(%p)->(%p)\n", This, stylesheet);
01660     return E_NOTIMPL;
01661 }
01662 
01663 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
01664 {
01665     xmlnode_QueryInterface,
01666     xmlnode_AddRef,
01667     xmlnode_Release,
01668     xmlnode_GetTypeInfoCount,
01669     xmlnode_GetTypeInfo,
01670     xmlnode_GetIDsOfNames,
01671     xmlnode_Invoke,
01672     xmlnode_get_nodeName,
01673     xmlnode_get_nodeValue,
01674     xmlnode_put_nodeValue,
01675     xmlnode_get_nodeType,
01676     xmlnode_get_parentNode,
01677     xmlnode_get_childNodes,
01678     xmlnode_get_firstChild,
01679     xmlnode_get_lastChild,
01680     xmlnode_get_previousSibling,
01681     xmlnode_get_nextSibling,
01682     xmlnode_get_attributes,
01683     xmlnode_insertBefore,
01684     xmlnode_replaceChild,
01685     xmlnode_removeChild,
01686     xmlnode_appendChild,
01687     xmlnode_hasChildNodes,
01688     xmlnode_get_ownerDocument,
01689     xmlnode_cloneNode,
01690     xmlnode_get_nodeTypeString,
01691     xmlnode_get_text,
01692     xmlnode_put_text,
01693     xmlnode_get_specified,
01694     xmlnode_get_definition,
01695     xmlnode_get_nodeTypedValue,
01696     xmlnode_put_nodeTypedValue,
01697     xmlnode_get_dataType,
01698     xmlnode_put_dataType,
01699     xmlnode_get_xml,
01700     xmlnode_transformNode,
01701     xmlnode_selectNodes,
01702     xmlnode_selectSingleNode,
01703     xmlnode_get_parsed,
01704     xmlnode_get_namespaceURI,
01705     xmlnode_get_prefix,
01706     xmlnode_get_baseName,
01707     xmlnode_transformNodeToObject,
01708 };
01709 
01710 void destroy_xmlnode(xmlnode *This)
01711 {
01712     if(This->node)
01713         xmldoc_release(This->node->doc);
01714 }
01715 
01716 void init_xmlnode(xmlnode *This, xmlNodePtr node, IUnknown *outer, dispex_static_data_t *dispex_data )
01717 {
01718     if(node)
01719         xmldoc_add_ref( node->doc );
01720 
01721     This->lpVtbl = &xmlnode_vtbl;
01722     This->ref = 1;
01723     This->node = node;
01724     This->pUnkOuter = outer;
01725 
01726     if(dispex_data)
01727         init_dispex(&This->dispex, This->pUnkOuter, dispex_data);
01728 }
01729 
01730 IXMLDOMNode *create_node( xmlNodePtr node )
01731 {
01732     IUnknown *pUnk;
01733     IXMLDOMNode *ret;
01734     HRESULT hr;
01735 
01736     if ( !node )
01737         return NULL;
01738 
01739     TRACE("type %d\n", node->type);
01740     switch(node->type)
01741     {
01742     case XML_ELEMENT_NODE:
01743         pUnk = create_element( node );
01744         break;
01745     case XML_ATTRIBUTE_NODE:
01746         pUnk = create_attribute( node );
01747         break;
01748     case XML_TEXT_NODE:
01749         pUnk = create_text( node );
01750         break;
01751     case XML_CDATA_SECTION_NODE:
01752         pUnk = create_cdata( node );
01753         break;
01754     case XML_ENTITY_REF_NODE:
01755         pUnk = create_doc_entity_ref( node );
01756         break;
01757     case XML_PI_NODE:
01758         pUnk = create_pi( node );
01759         break;
01760     case XML_COMMENT_NODE:
01761         pUnk = create_comment( node );
01762         break;
01763     case XML_DOCUMENT_NODE:
01764         pUnk = create_domdoc( node );
01765         break;
01766     case XML_DOCUMENT_FRAG_NODE:
01767         pUnk = create_doc_fragment( node );
01768         break;
01769     default: {
01770         xmlnode *new_node;
01771 
01772         FIXME("only creating basic node for type %d\n", node->type);
01773 
01774         new_node = heap_alloc(sizeof(xmlnode));
01775         if(!new_node)
01776             return NULL;
01777 
01778         init_xmlnode(new_node, node, NULL, NULL);
01779         pUnk = (IUnknown*)IXMLDOMNode_from_impl(new_node);
01780     }
01781     }
01782 
01783     hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
01784     IUnknown_Release(pUnk);
01785     if(FAILED(hr)) return NULL;
01786     return ret;
01787 }
01788 #endif

Generated on Sun May 27 2012 04:25:24 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.