Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennode.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
1.7.6.1
|