From: Amine Khaldi Date: Thu, 3 Mar 2016 14:00:49 +0000 (+0000) Subject: [MSXML3] Sync with Wine Staging 1.9.4. CORE-10912 X-Git-Tag: ReactOS-0.4.1~330 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=ce187684eb5e1f02404becab9f85a1dee41fde8a [MSXML3] Sync with Wine Staging 1.9.4. CORE-10912 svn path=/trunk/; revision=70885 --- diff --git a/reactos/dll/win32/msxml3/domdoc.c b/reactos/dll/win32/msxml3/domdoc.c index 670741ec933..b1ffb33e31e 100644 --- a/reactos/dll/win32/msxml3/domdoc.c +++ b/reactos/dll/win32/msxml3/domdoc.c @@ -428,7 +428,14 @@ static void sax_characters(void *ctx, const xmlChar *ch, int len) (!ctxt->node->last || ((ctxt->node->last && (cur == '<' || ctxt->node->last->type != XML_TEXT_NODE)) ))) + { + /* Keep information about ignorable whitespace text node in previous or parent node */ + if (ctxt->node->last) + *(DWORD*)&ctxt->node->last->_private |= NODE_PRIV_TRAILING_IGNORABLE_WS; + else if (ctxt->node->type != XML_DOCUMENT_NODE) + *(DWORD*)&ctxt->node->_private |= NODE_PRIV_CHILD_IGNORABLE_WS; return; + } } xmlSAX2Characters(ctxt, ch, len); @@ -1217,8 +1224,31 @@ static HRESULT WINAPI domdoc_cloneNode( IXMLDOMNode** outNode) { domdoc *This = impl_from_IXMLDOMDocument3( iface ); + xmlNodePtr clone; + TRACE("(%p)->(%d %p)\n", This, deep, outNode); - return node_clone( &This->node, deep, outNode ); + + if (!outNode) + return E_INVALIDARG; + + *outNode = NULL; + + clone = xmlCopyNode((xmlNodePtr)get_doc(This), deep ? 1 : 2); + if (!clone) + return E_FAIL; + + clone->doc->_private = create_priv(); + xmldoc_add_orphan(clone->doc, clone); + xmldoc_add_ref(clone->doc); + + priv_from_xmlDocPtr(clone->doc)->properties = copy_properties(This->properties); + if (!(*outNode = (IXMLDOMNode*)create_domdoc(clone))) + { + xmldoc_release(clone->doc); + return E_FAIL; + } + + return S_OK; } @@ -3613,16 +3643,16 @@ HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj) IUnknown* create_domdoc( xmlNodePtr document ) { - void* pObj = NULL; + IUnknown *obj = NULL; HRESULT hr; TRACE("(%p)\n", document); - hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj); + hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&obj); if (FAILED(hr)) return NULL; - return pObj; + return obj; } #else diff --git a/reactos/dll/win32/msxml3/httprequest.c b/reactos/dll/win32/msxml3/httprequest.c index ea22ebf2a12..85f72f7388a 100644 --- a/reactos/dll/win32/msxml3/httprequest.c +++ b/reactos/dll/win32/msxml3/httprequest.c @@ -152,6 +152,19 @@ static void free_response_headers(httprequest *This) This->raw_respheaders = NULL; } +static void free_request_headers(httprequest *This) +{ + struct httpheader *header, *header2; + + LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct httpheader, entry) + { + list_remove(&header->entry); + SysFreeString(header->header); + SysFreeString(header->value); + heap_free(header); + } +} + struct BindStatusCallback { IBindStatusCallback IBindStatusCallback_iface; @@ -864,6 +877,7 @@ static HRESULT httprequest_open(httprequest *This, BSTR method, BSTR url, SysFreeString(This->user); SysFreeString(This->password); This->user = This->password = NULL; + free_request_headers(This); if (!strcmpiW(method, MethodGetW)) { @@ -1249,8 +1263,6 @@ static HRESULT httprequest_put_onreadystatechange(httprequest *This, IDispatch * static void httprequest_release(httprequest *This) { - struct httpheader *header, *header2; - if (This->site) IUnknown_Release( This->site ); if (This->uri) @@ -1262,15 +1274,8 @@ static void httprequest_release(httprequest *This) SysFreeString(This->user); SysFreeString(This->password); - /* request headers */ - LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct httpheader, entry) - { - list_remove(&header->entry); - SysFreeString(header->header); - SysFreeString(header->value); - heap_free(header); - } - /* response headers */ + /* cleanup headers lists */ + free_request_headers(This); free_response_headers(This); SysFreeString(This->status_text); diff --git a/reactos/dll/win32/msxml3/msxml_private.h b/reactos/dll/win32/msxml3/msxml_private.h index add547c084c..dd124c59c41 100644 --- a/reactos/dll/win32/msxml3/msxml_private.h +++ b/reactos/dll/win32/msxml3/msxml_private.h @@ -559,4 +559,7 @@ HRESULT detach_bsc(bsc_t*) DECLSPEC_HIDDEN; /* ... */ #define E_XML_REQUIRED_ATTRIBUTE_MISSING 0xC00CE020 +#define NODE_PRIV_TRAILING_IGNORABLE_WS 0x40000000 +#define NODE_PRIV_CHILD_IGNORABLE_WS 0x80000000 +#define NODE_PRIV_REFCOUNT_MASK ~(NODE_PRIV_TRAILING_IGNORABLE_WS|NODE_PRIV_CHILD_IGNORABLE_WS) #endif /* __MSXML_PRIVATE__ */ diff --git a/reactos/dll/win32/msxml3/node.c b/reactos/dll/win32/msxml3/node.c index 37bd57b7750..7e9efae7e7d 100644 --- a/reactos/dll/win32/msxml3/node.c +++ b/reactos/dll/win32/msxml3/node.c @@ -379,7 +379,7 @@ HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret) static int node_get_inst_cnt(xmlNodePtr node) { - int ret = *(LONG *)&node->_private; + int ret = *(LONG *)&node->_private & NODE_PRIV_REFCOUNT_MASK; xmlNodePtr child; /* add attribute counts */ @@ -410,6 +410,20 @@ int xmlnode_get_inst_cnt(xmlnode *node) return node_get_inst_cnt(node->node); } +/* _private field holds a number of COM instances spawned from this libxml2 node + * most significant bits are used to store information about ignorrable whitespace nodes */ +static void xmlnode_add_ref(xmlNodePtr node) +{ + if (node->type == XML_DOCUMENT_NODE) return; + InterlockedIncrement((LONG*)&node->_private); +} + +static void xmlnode_release(xmlNodePtr node) +{ + if (node->type == XML_DOCUMENT_NODE) return; + InterlockedDecrement((LONG*)&node->_private); +} + HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child, IXMLDOMNode **ret) { @@ -470,6 +484,7 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT if(before) { + xmlNodePtr new_node; xmlnode *before_node_obj = get_node_obj(before); /* refs count including subtree */ @@ -477,19 +492,35 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT refcount = xmlnode_get_inst_cnt(node_obj); if (refcount) xmldoc_add_refs(before_node_obj->node->doc, refcount); - node_obj->node = xmlAddPrevSibling(before_node_obj->node, node_obj->node); + new_node = xmlAddPrevSibling(before_node_obj->node, node_obj->node); + if (new_node != node_obj->node) + { + if (refcount != 1) + FIXME("referenced xmlNode was freed, expect crashes\n"); + xmlnode_add_ref(new_node); + node_obj->node = new_node; + } if (refcount) xmldoc_release_refs(doc, refcount); node_obj->parent = This->parent; } else { + xmlNodePtr new_node; + if (doc != This->node->doc) refcount = xmlnode_get_inst_cnt(node_obj); if (refcount) xmldoc_add_refs(This->node->doc, refcount); /* xmlAddChild doesn't unlink node from previous parent */ xmlUnlinkNode(node_obj->node); - node_obj->node = xmlAddChild(This->node, node_obj->node); + new_node = xmlAddChild(This->node, node_obj->node); + if (new_node != node_obj->node) + { + if (refcount != 1) + FIXME("referenced xmlNode was freed, expect crashes\n"); + xmlnode_add_ref(new_node); + node_obj->node = new_node; + } if (refcount) xmldoc_release_refs(doc, refcount); node_obj->parent = This->iface; } @@ -673,48 +704,63 @@ HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode) return S_OK; } -static inline xmlChar* trim_whitespace(xmlChar* str) -{ - xmlChar* ret = str; - int len; - - if (!str) - return NULL; - - while (*ret && isspace(*ret)) - ++ret; - len = xmlStrlen(ret); - if (len) - while (isspace(ret[len-1])) --len; - - ret = xmlStrndup(ret, len); - xmlFree(str); - return ret; -} - -static xmlChar* do_get_text(xmlNodePtr node) +static xmlChar* do_get_text(xmlNodePtr node, BOOL trim, DWORD *first, DWORD *last, BOOL *trail_ig_ws) { xmlNodePtr child; xmlChar* str; BOOL preserving = is_preserving_whitespace(node); + *first = -1; + *last = 0; + if (!node->children) { str = xmlNodeGetContent(node); + *trail_ig_ws = *(DWORD*)&node->_private & NODE_PRIV_CHILD_IGNORABLE_WS; } else { - xmlElementType prev_type = XML_TEXT_NODE; + BOOL ig_ws = FALSE; xmlChar* tmp; + DWORD pos = 0; str = xmlStrdup(BAD_CAST ""); + + if (node->type != XML_DOCUMENT_NODE) + ig_ws = *(DWORD*)&node->_private & NODE_PRIV_CHILD_IGNORABLE_WS; + *trail_ig_ws = FALSE; + for (child = node->children; child != NULL; child = child->next) { switch (child->type) { - case XML_ELEMENT_NODE: - tmp = do_get_text(child); + case XML_ELEMENT_NODE: { + DWORD node_first, node_last; + + tmp = do_get_text(child, FALSE, &node_first, &node_last, trail_ig_ws); + + if (node_first!=-1 && pos+node_first<*first) + *first = pos+node_first; + if (node_last && pos+node_last>*last) + *last = pos+node_last; break; + } case XML_TEXT_NODE: + tmp = xmlNodeGetContent(child); + if (!preserving && tmp[0]) + { + xmlChar *beg; + + for (beg = tmp; *beg; beg++) + if (!isspace(*beg)) break; + + if (!*beg) + { + ig_ws = TRUE; + xmlFree(tmp); + tmp = NULL; + } + } + break; case XML_CDATA_SECTION_NODE: case XML_ENTITY_REF_NODE: case XML_ENTITY_NODE: @@ -725,18 +771,33 @@ static xmlChar* do_get_text(xmlNodePtr node) break; } - if (tmp) + if ((tmp && *tmp) || child->type==XML_CDATA_SECTION_NODE) { - if (*tmp) + if (ig_ws && str[0]) { - if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE) - str = xmlStrcat(str, BAD_CAST " "); - str = xmlStrcat(str, tmp); - prev_type = child->type; + str = xmlStrcat(str, BAD_CAST " "); + pos++; } - xmlFree(tmp); + if (tmp && *tmp) str = xmlStrcat(str, tmp); + if (child->type==XML_CDATA_SECTION_NODE && pos<*first) + *first = pos; + if (tmp && *tmp) pos += xmlStrlen(tmp); + if (child->type==XML_CDATA_SECTION_NODE && pos>*last) + *last = pos; + ig_ws = FALSE; } + if (tmp) xmlFree(tmp); + + if (!ig_ws) + { + ig_ws = *(DWORD*)&child->_private & NODE_PRIV_TRAILING_IGNORABLE_WS; + } + if (!ig_ws) + ig_ws = *trail_ig_ws; + *trail_ig_ws = FALSE; } + + *trail_ig_ws = ig_ws; } switch (node->type) @@ -747,8 +808,24 @@ static xmlChar* do_get_text(xmlNodePtr node) case XML_ENTITY_NODE: case XML_DOCUMENT_NODE: case XML_DOCUMENT_FRAG_NODE: - if (!preserving) - str = trim_whitespace(str); + if (trim && !preserving) + { + xmlChar* ret = str; + int len; + + if (!str) + break; + + for (ret = str; *ret && isspace(*ret) && (*first)--; ret++) + if (*last) (*last)--; + for (len = xmlStrlen(ret)-1; len >= 0 && len >= *last; len--) + if(!isspace(ret[len])) break; + + ret = xmlStrndup(ret, len+1); + xmlFree(str); + str = ret; + break; + } break; default: break; @@ -761,10 +838,12 @@ HRESULT node_get_text(const xmlnode *This, BSTR *text) { BSTR str = NULL; xmlChar *content; + DWORD first, last; + BOOL tmp; if (!text) return E_INVALIDARG; - content = do_get_text(This->node); + content = do_get_text(This->node, TRUE, &first, &last, &tmp); if (content) { str = bstr_from_xmlChar(content); @@ -1373,19 +1452,6 @@ HRESULT node_get_base_name(xmlnode *This, BSTR *name) return S_OK; } -/* _private field holds a number of COM instances spawned from this libxml2 node */ -static void xmlnode_add_ref(xmlNodePtr node) -{ - if (node->type == XML_DOCUMENT_NODE) return; - InterlockedIncrement((LONG*)&node->_private); -} - -static void xmlnode_release(xmlNodePtr node) -{ - if (node->type == XML_DOCUMENT_NODE) return; - InterlockedDecrement((LONG*)&node->_private); -} - void destroy_xmlnode(xmlnode *This) { if(This->node) diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index b1703ec3eb1..3697cbaab78 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -131,7 +131,7 @@ reactos/dll/win32/msvfw32 # Synced to WineStaging-1.7.55 reactos/dll/win32/msvidc32 # Synced to WineStaging-1.7.55 reactos/dll/win32/msxml # Synced to WineStaging-1.7.55 reactos/dll/win32/msxml2 # Synced to WineStaging-1.7.55 -reactos/dll/win32/msxml3 # Synced to WineStaging-1.7.55 +reactos/dll/win32/msxml3 # Synced to WineStaging-1.9.4 reactos/dll/win32/msxml4 # Synced to WineStaging-1.7.55 reactos/dll/win32/msxml6 # Synced to WineStaging-1.7.55 reactos/dll/win32/nddeapi # Synced to WineStaging-1.7.55