[MSXML3] Sync with Wine Staging 1.9.4. CORE-10912

svn path=/trunk/; revision=70885
This commit is contained in:
Amine Khaldi 2016-03-03 14:00:49 +00:00
parent 565ee09080
commit ce187684eb
5 changed files with 169 additions and 65 deletions

View file

@ -428,7 +428,14 @@ static void sax_characters(void *ctx, const xmlChar *ch, int len)
(!ctxt->node->last || (!ctxt->node->last ||
((ctxt->node->last && (cur == '<' || ctxt->node->last->type != XML_TEXT_NODE)) ((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; return;
}
} }
xmlSAX2Characters(ctxt, ch, len); xmlSAX2Characters(ctxt, ch, len);
@ -1217,8 +1224,31 @@ static HRESULT WINAPI domdoc_cloneNode(
IXMLDOMNode** outNode) IXMLDOMNode** outNode)
{ {
domdoc *This = impl_from_IXMLDOMDocument3( iface ); domdoc *This = impl_from_IXMLDOMDocument3( iface );
xmlNodePtr clone;
TRACE("(%p)->(%d %p)\n", This, deep, outNode); 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 ) IUnknown* create_domdoc( xmlNodePtr document )
{ {
void* pObj = NULL; IUnknown *obj = NULL;
HRESULT hr; HRESULT hr;
TRACE("(%p)\n", document); 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)) if (FAILED(hr))
return NULL; return NULL;
return pObj; return obj;
} }
#else #else

View file

@ -152,6 +152,19 @@ static void free_response_headers(httprequest *This)
This->raw_respheaders = NULL; 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 struct BindStatusCallback
{ {
IBindStatusCallback IBindStatusCallback_iface; IBindStatusCallback IBindStatusCallback_iface;
@ -864,6 +877,7 @@ static HRESULT httprequest_open(httprequest *This, BSTR method, BSTR url,
SysFreeString(This->user); SysFreeString(This->user);
SysFreeString(This->password); SysFreeString(This->password);
This->user = This->password = NULL; This->user = This->password = NULL;
free_request_headers(This);
if (!strcmpiW(method, MethodGetW)) if (!strcmpiW(method, MethodGetW))
{ {
@ -1249,8 +1263,6 @@ static HRESULT httprequest_put_onreadystatechange(httprequest *This, IDispatch *
static void httprequest_release(httprequest *This) static void httprequest_release(httprequest *This)
{ {
struct httpheader *header, *header2;
if (This->site) if (This->site)
IUnknown_Release( This->site ); IUnknown_Release( This->site );
if (This->uri) if (This->uri)
@ -1262,15 +1274,8 @@ static void httprequest_release(httprequest *This)
SysFreeString(This->user); SysFreeString(This->user);
SysFreeString(This->password); SysFreeString(This->password);
/* request headers */ /* cleanup headers lists */
LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct httpheader, entry) free_request_headers(This);
{
list_remove(&header->entry);
SysFreeString(header->header);
SysFreeString(header->value);
heap_free(header);
}
/* response headers */
free_response_headers(This); free_response_headers(This);
SysFreeString(This->status_text); SysFreeString(This->status_text);

View file

@ -559,4 +559,7 @@ HRESULT detach_bsc(bsc_t*) DECLSPEC_HIDDEN;
/* ... */ /* ... */
#define E_XML_REQUIRED_ATTRIBUTE_MISSING 0xC00CE020 #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__ */ #endif /* __MSXML_PRIVATE__ */

View file

@ -379,7 +379,7 @@ HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
static int node_get_inst_cnt(xmlNodePtr node) static int node_get_inst_cnt(xmlNodePtr node)
{ {
int ret = *(LONG *)&node->_private; int ret = *(LONG *)&node->_private & NODE_PRIV_REFCOUNT_MASK;
xmlNodePtr child; xmlNodePtr child;
/* add attribute counts */ /* add attribute counts */
@ -410,6 +410,20 @@ int xmlnode_get_inst_cnt(xmlnode *node)
return node_get_inst_cnt(node->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, HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
IXMLDOMNode **ret) IXMLDOMNode **ret)
{ {
@ -470,6 +484,7 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
if(before) if(before)
{ {
xmlNodePtr new_node;
xmlnode *before_node_obj = get_node_obj(before); xmlnode *before_node_obj = get_node_obj(before);
/* refs count including subtree */ /* 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); refcount = xmlnode_get_inst_cnt(node_obj);
if (refcount) xmldoc_add_refs(before_node_obj->node->doc, refcount); 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); if (refcount) xmldoc_release_refs(doc, refcount);
node_obj->parent = This->parent; node_obj->parent = This->parent;
} }
else else
{ {
xmlNodePtr new_node;
if (doc != This->node->doc) if (doc != This->node->doc)
refcount = xmlnode_get_inst_cnt(node_obj); refcount = xmlnode_get_inst_cnt(node_obj);
if (refcount) xmldoc_add_refs(This->node->doc, refcount); if (refcount) xmldoc_add_refs(This->node->doc, refcount);
/* xmlAddChild doesn't unlink node from previous parent */ /* xmlAddChild doesn't unlink node from previous parent */
xmlUnlinkNode(node_obj->node); 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); if (refcount) xmldoc_release_refs(doc, refcount);
node_obj->parent = This->iface; node_obj->parent = This->iface;
} }
@ -673,48 +704,63 @@ HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
return S_OK; return S_OK;
} }
static inline xmlChar* trim_whitespace(xmlChar* str) static xmlChar* do_get_text(xmlNodePtr node, BOOL trim, DWORD *first, DWORD *last, BOOL *trail_ig_ws)
{
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)
{ {
xmlNodePtr child; xmlNodePtr child;
xmlChar* str; xmlChar* str;
BOOL preserving = is_preserving_whitespace(node); BOOL preserving = is_preserving_whitespace(node);
*first = -1;
*last = 0;
if (!node->children) if (!node->children)
{ {
str = xmlNodeGetContent(node); str = xmlNodeGetContent(node);
*trail_ig_ws = *(DWORD*)&node->_private & NODE_PRIV_CHILD_IGNORABLE_WS;
} }
else else
{ {
xmlElementType prev_type = XML_TEXT_NODE; BOOL ig_ws = FALSE;
xmlChar* tmp; xmlChar* tmp;
DWORD pos = 0;
str = xmlStrdup(BAD_CAST ""); 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) for (child = node->children; child != NULL; child = child->next)
{ {
switch (child->type) switch (child->type)
{ {
case XML_ELEMENT_NODE: case XML_ELEMENT_NODE: {
tmp = do_get_text(child); 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; break;
}
case XML_TEXT_NODE: 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_CDATA_SECTION_NODE:
case XML_ENTITY_REF_NODE: case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE: case XML_ENTITY_NODE:
@ -725,18 +771,33 @@ static xmlChar* do_get_text(xmlNodePtr node)
break; 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, BAD_CAST " "); pos++;
str = xmlStrcat(str, tmp);
prev_type = child->type;
} }
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) switch (node->type)
@ -747,8 +808,24 @@ static xmlChar* do_get_text(xmlNodePtr node)
case XML_ENTITY_NODE: case XML_ENTITY_NODE:
case XML_DOCUMENT_NODE: case XML_DOCUMENT_NODE:
case XML_DOCUMENT_FRAG_NODE: case XML_DOCUMENT_FRAG_NODE:
if (!preserving) if (trim && !preserving)
str = trim_whitespace(str); {
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; break;
default: default:
break; break;
@ -761,10 +838,12 @@ HRESULT node_get_text(const xmlnode *This, BSTR *text)
{ {
BSTR str = NULL; BSTR str = NULL;
xmlChar *content; xmlChar *content;
DWORD first, last;
BOOL tmp;
if (!text) return E_INVALIDARG; if (!text) return E_INVALIDARG;
content = do_get_text(This->node); content = do_get_text(This->node, TRUE, &first, &last, &tmp);
if (content) if (content)
{ {
str = bstr_from_xmlChar(content); str = bstr_from_xmlChar(content);
@ -1373,19 +1452,6 @@ HRESULT node_get_base_name(xmlnode *This, BSTR *name)
return S_OK; 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) void destroy_xmlnode(xmlnode *This)
{ {
if(This->node) if(This->node)

View file

@ -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/msvidc32 # Synced to WineStaging-1.7.55
reactos/dll/win32/msxml # 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/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/msxml4 # Synced to WineStaging-1.7.55
reactos/dll/win32/msxml6 # 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 reactos/dll/win32/nddeapi # Synced to WineStaging-1.7.55