[PATCH 1/2] msxml3: Implement property SelectionNamespaces for XPath & move domdoc properties to their own struct so we can easily preserve them on reload.
Adam Martinson
amartinson at codeweavers.com
Tue Sep 21 13:17:05 CDT 2010
---
dlls/msxml3/domdoc.c | 344 ++++++++++++++++++++++++++++++++++++++------
dlls/msxml3/queryresult.c | 3 +
dlls/msxml3/tests/domdoc.c | 46 ++++---
3 files changed, 333 insertions(+), 60 deletions(-)
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index 8f87a56..dbc71c4 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -2,6 +2,7 @@
* DOM Document implementation
*
* Copyright 2005 Mike McCormack
+ * Copyright 2010 Adam Martinson for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -47,6 +48,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
#ifdef HAVE_LIBXML2
+#include <libxml/xpathInternals.h>
#include <libxml/xmlsave.h>
/* not defined in older versions */
@@ -64,6 +66,16 @@ static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D'
static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
+/* Data used by domdoc_getProperty()/domdoc_setProperty().
+ * We need to preserve this when reloading a document,
+ * and also need access to it from the libxml backend. */
+typedef struct _domdoc_properties {
+ struct list selectNsList;
+ xmlChar const* selectNsStr;
+ LONG selectNsStr_len;
+ BOOL XPath;
+} domdoc_properties;
+
typedef struct _domdoc
{
xmlnode node;
@@ -77,6 +89,7 @@ typedef struct _domdoc
VARIANT_BOOL validating;
VARIANT_BOOL resolving;
VARIANT_BOOL preserving;
+ domdoc_properties* properties;
IXMLDOMSchemaCollection *schema;
bsc_t *bsc;
HRESULT error;
@@ -116,7 +129,7 @@ typedef struct _domdoc
typedef struct _xmldoc_priv {
LONG refs;
struct list orphans;
- BOOL XPath;
+ domdoc_properties* properties;
} xmldoc_priv;
typedef struct _orphan_entry {
@@ -124,24 +137,54 @@ typedef struct _orphan_entry {
xmlNode * node;
} orphan_entry;
+typedef struct _select_ns_entry {
+ struct list entry;
+ xmlChar const* prefix;
+ xmlChar prefix_end;
+ xmlChar const* href;
+ xmlChar href_end;
+} select_ns_entry;
+
static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
{
return doc->_private;
}
-static inline BOOL is_xpathmode(const xmlDocPtr doc)
+static inline domdoc_properties * properties_from_xmlDocPtr(const xmlDocPtr doc)
{
- return priv_from_xmlDocPtr(doc)->XPath;
+ return priv_from_xmlDocPtr(doc)->properties;
}
-static inline void set_xpathmode(const xmlDocPtr doc)
+int registerNamespaces(xmlXPathContextPtr ctxt)
{
- priv_from_xmlDocPtr(doc)->XPath = TRUE;
+ int n = 0;
+ const select_ns_entry* ns = NULL;
+ const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
+
+ TRACE("(%p)\n", ctxt);
+
+ LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
+ {
+ xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
+ ++n;
+ }
+
+ return n;
}
-static inline void reset_xpathmode(const xmlDocPtr doc)
+static inline void clear_selectNsList(struct list* pNsList)
{
- priv_from_xmlDocPtr(doc)->XPath = FALSE;
+ select_ns_entry *ns, *ns2;
+ LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
+ {
+ heap_free( ns );
+ }
+ list_init(pNsList);
+}
+
+static inline BOOL is_xpathmode(const xmlDocPtr doc)
+{
+ return properties_from_xmlDocPtr(doc)->XPath;
}
static xmldoc_priv * create_priv(void)
@@ -152,13 +195,73 @@ static xmldoc_priv * create_priv(void)
if (priv)
{
priv->refs = 0;
- priv->XPath = FALSE;
list_init( &priv->orphans );
+ priv->properties = NULL;
}
return priv;
}
+static domdoc_properties * create_properties(const GUID *clsid)
+{
+ domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
+
+ list_init( &properties->selectNsList );
+ properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
+ properties->selectNsStr_len = 0;
+ properties->XPath = FALSE;
+
+ /* properties that are dependent on object versions */
+ if (IsEqualCLSID( clsid, &CLSID_DOMDocument40 ) ||
+ IsEqualCLSID( clsid, &CLSID_DOMDocument60 ))
+ {
+ properties->XPath = TRUE;
+ }
+
+ return properties;
+}
+
+static domdoc_properties* copy_properties(domdoc_properties const* properties)
+{
+ domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
+ select_ns_entry const* ns = NULL;
+ select_ns_entry* new_ns = NULL;
+ int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
+ ptrdiff_t offset;
+
+ if (pcopy)
+ {
+ pcopy->XPath = properties->XPath;
+ pcopy->selectNsStr_len = properties->selectNsStr_len;
+ list_init( &pcopy->selectNsList );
+ pcopy->selectNsStr = heap_alloc(len);
+ memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
+ offset = pcopy->selectNsStr - properties->selectNsStr;
+
+ LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
+ {
+ new_ns = heap_alloc(sizeof(select_ns_entry));
+ memcpy(new_ns, ns, sizeof(select_ns_entry));
+ new_ns->href += offset;
+ new_ns->prefix += offset;
+ list_add_tail(&pcopy->selectNsList, &new_ns->entry);
+ }
+
+ }
+
+ return pcopy;
+}
+
+static void free_properties(domdoc_properties* properties)
+{
+ if (properties)
+ {
+ clear_selectNsList(&properties->selectNsList);
+ heap_free((xmlChar*)properties->selectNsStr);
+ heap_free(properties);
+ }
+}
+
/* links a "<?xml" node as a first child */
void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
{
@@ -252,6 +355,7 @@ LONG xmldoc_release(xmlDocPtr doc)
xmlFreeNode( orphan->node );
heap_free( orphan );
}
+ free_properties(priv->properties);
heap_free(doc->_private);
xmlFreeDoc(doc);
@@ -292,14 +396,28 @@ HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
return S_FALSE;
}
-static HRESULT attach_xmldoc( xmlnode *node, xmlDocPtr xml )
+static inline xmlDocPtr get_doc( domdoc *This )
{
- if(node->node)
- xmldoc_release(node->node->doc);
+ return (xmlDocPtr)This->node.node;
+}
- node->node = (xmlNodePtr) xml;
- if(node->node)
- xmldoc_add_ref(node->node->doc);
+static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
+{
+ if(This->node.node)
+ {
+ priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
+ if (xmldoc_release(get_doc(This)) != 0)
+ priv_from_xmlDocPtr(get_doc(This))->properties =
+ copy_properties(This->properties);
+ }
+
+ This->node.node = (xmlNodePtr) xml;
+
+ if(This->node.node)
+ {
+ xmldoc_add_ref(get_doc(This));
+ priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
+ }
return S_OK;
}
@@ -309,11 +427,6 @@ static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
}
-static inline xmlDocPtr get_doc( domdoc *This )
-{
- return (xmlDocPtr)This->node.node;
-}
-
static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
{
return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
@@ -429,7 +542,7 @@ static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
xmldoc->_private = create_priv();
- return attach_xmldoc( &This->node, xmldoc );
+ return attach_xmldoc(This, xmldoc);
}
static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
@@ -1608,7 +1721,7 @@ static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
xmldoc = doparse( ptr, len, NULL );
if(xmldoc) {
xmldoc->_private = create_priv();
- return attach_xmldoc(&This->node, xmldoc);
+ return attach_xmldoc(This, xmldoc);
}
return S_OK;
@@ -1661,7 +1774,7 @@ static HRESULT WINAPI domdoc_load(
{
domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
- hr = attach_xmldoc(&This->node, xmldoc);
+ hr = attach_xmldoc(This, xmldoc);
if(SUCCEEDED(hr))
*isSuccessful = VARIANT_TRUE;
@@ -1723,7 +1836,7 @@ static HRESULT WINAPI domdoc_load(
if(!filename || FAILED(hr)) {
xmldoc = xmlNewDoc(NULL);
xmldoc->_private = create_priv();
- hr = attach_xmldoc(&This->node, xmldoc);
+ hr = attach_xmldoc(This, xmldoc);
if(SUCCEEDED(hr))
hr = S_FALSE;
}
@@ -1859,7 +1972,8 @@ static HRESULT WINAPI domdoc_loadXML(
xmldoc = xmlNewDoc(NULL);
xmldoc->_private = create_priv();
- hr2 = attach_xmldoc( &This->node, xmldoc );
+
+ hr2 = attach_xmldoc(This, xmldoc);
if( FAILED(hr2) )
hr = hr2;
@@ -2155,27 +2269,146 @@ static HRESULT WINAPI domdoc_setProperty(
hr = S_OK;
if (lstrcmpiW(bstr, PropValueXPathW) == 0)
- set_xpathmode(get_doc(This));
+ This->properties->XPath = TRUE;
else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
- reset_xpathmode(get_doc(This));
+ This->properties->XPath = FALSE;
else
hr = E_FAIL;
VariantClear(&varStr);
return hr;
}
+ else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
+ {
+ VARIANT varStr;
+ HRESULT hr;
+ BSTR bstr;
+ xmlChar *pTokBegin, *pTokEnd, *pTokInner;
+ xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
+ xmlXPathContextPtr ctx;
+ struct list *pNsList;
+ select_ns_entry* pNsEntry = NULL;
+
+ V_VT(&varStr) = VT_EMPTY;
+ if (V_VT(&var) != VT_BSTR)
+ {
+ if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
+ return hr;
+ bstr = V_BSTR(&varStr);
+ }
+ else
+ bstr = V_BSTR(&var);
+
+ hr = S_OK;
+
+ pNsList = &(This->properties->selectNsList);
+ clear_selectNsList(pNsList);
+ heap_free(nsStr);
+ nsStr = xmlChar_from_wchar(bstr);
+
+
+ TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
+
+ This->properties->selectNsStr = nsStr;
+ This->properties->selectNsStr_len = xmlStrlen(nsStr);
+ if (bstr && *bstr)
+ {
+ ctx = xmlXPathNewContext(get_doc(This));
+ pTokBegin = nsStr;
+ pTokEnd = nsStr;
+ for (; *pTokBegin; pTokBegin = pTokEnd)
+ {
+ if (pNsEntry != NULL)
+ memset(pNsEntry, 0, sizeof(select_ns_entry));
+ else
+ pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
+
+ while (*pTokBegin == ' ')
+ ++pTokBegin;
+ pTokEnd = pTokBegin;
+ while (*pTokEnd != ' ' && *pTokEnd != 0)
+ ++pTokEnd;
+
+ if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
+ {
+ hr = E_FAIL;
+ WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
+ wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
+ continue;
+ }
+
+ pTokBegin += 5;
+ if (*pTokBegin == '=')
+ {
+ /*valid for XSLPattern?*/
+ FIXME("Setting default xmlns not supported - skipping.\n");
+ pTokBegin = pTokEnd;
+ continue;
+ }
+ else if (*pTokBegin == ':')
+ {
+ pNsEntry->prefix = ++pTokBegin;
+ for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
+ ;
+
+ if (pTokInner == pTokEnd)
+ {
+ hr = E_FAIL;
+ WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
+ wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
+ continue;
+ }
+
+ pNsEntry->prefix_end = *pTokInner;
+ *pTokInner = 0;
+ ++pTokInner;
+
+ if (pTokEnd-pTokInner > 1 &&
+ ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
+ (*pTokInner == '"' && *(pTokEnd-1) == '"')))
+ {
+ pNsEntry->href = ++pTokInner;
+ pNsEntry->href_end = *(pTokEnd-1);
+ *(pTokEnd-1) = 0;
+ list_add_tail(pNsList, &pNsEntry->entry);
+ /*let libxml figure out if they're valid from here ;)*/
+ if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
+ {
+ hr = E_FAIL;
+ }
+ pNsEntry = NULL;
+ continue;
+ }
+ else
+ {
+ WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
+ wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
+ list_add_tail(pNsList, &pNsEntry->entry);
+
+ pNsEntry = NULL;
+ hr = E_FAIL;
+ continue;
+ }
+ }
+ else
+ {
+ hr = E_FAIL;
+ continue;
+ }
+ }
+ heap_free(pNsEntry);
+ xmlXPathFreeContext(ctx);
+ }
+
+ VariantClear(&varStr);
+ return hr;
+ }
else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0)
{
/* Ignore */
FIXME("Ignoring property ProhibitDTD, value %d\n", V_BOOL(&var));
return S_OK;
}
- else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
- {
- if (V_VT(&var) == VT_BSTR)
- FIXME("Unsupported SelectionNamespaces: %s\n", wine_dbgstr_w(V_BSTR(&var)));
- return E_FAIL;
- }
FIXME("Unknown property %s\n", wine_dbgstr_w(p));
return E_FAIL;
@@ -2196,11 +2429,46 @@ static HRESULT WINAPI domdoc_getProperty(
if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
{
V_VT(var) = VT_BSTR;
- V_BSTR(var) = is_xpathmode(This->node.node->doc) ?
+ V_BSTR(var) = This->properties->XPath?
SysAllocString(PropValueXPathW) :
SysAllocString(PropValueXSLPatternW);
return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
}
+ else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
+ {
+ int lenA, lenW;
+ BSTR rebuiltStr, cur;
+ const xmlChar *nsStr;
+ struct list *pNsList;
+ select_ns_entry* pNsEntry;
+
+ V_VT(var) = VT_BSTR;
+ nsStr = This->properties->selectNsStr;
+ pNsList = &This->properties->selectNsList;
+ lenA = This->properties->selectNsStr_len;
+ lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
+ rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
+ MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
+ cur = rebuiltStr;
+ /* this is fine because all of the chars that end tokens are ASCII*/
+ LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
+ {
+ while (*cur != 0) ++cur;
+ if (pNsEntry->prefix_end)
+ {
+ *cur = pNsEntry->prefix_end;
+ while (*cur != 0) ++cur;
+ }
+
+ if (pNsEntry->href_end)
+ {
+ *cur = pNsEntry->href_end;
+ }
+ }
+ V_BSTR(var) = SysAllocString(rebuiltStr);
+ heap_free(rebuiltStr);
+ return S_OK;
+ }
FIXME("Unknown property %s\n", wine_dbgstr_w(p));
return E_FAIL;
@@ -2476,6 +2744,7 @@ HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **docu
doc->validating = 0;
doc->resolving = 0;
doc->preserving = 0;
+ doc->properties = properties_from_xmlDocPtr(xmldoc);
doc->error = S_OK;
doc->schema = NULL;
doc->stream = NULL;
@@ -2503,6 +2772,7 @@ HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
return E_OUTOFMEMORY;
xmldoc->_private = create_priv();
+ priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
if(FAILED(hr))
@@ -2511,14 +2781,6 @@ HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
return hr;
}
- /* properties that are dependent on object versions */
- if (IsEqualCLSID( clsid, &CLSID_DOMDocument40 ) ||
- IsEqualCLSID( clsid, &CLSID_DOMDocument60 ))
- {
- domdoc *This = impl_from_IXMLDOMDocument3(*ppObj);
- set_xpathmode(get_doc(This));
- }
-
return hr;
}
diff --git a/dlls/msxml3/queryresult.c b/dlls/msxml3/queryresult.c
index 33a2f41..efaeb4b 100644
--- a/dlls/msxml3/queryresult.c
+++ b/dlls/msxml3/queryresult.c
@@ -3,6 +3,7 @@
*
* Copyright 2005 Mike McCormack
* Copyright 2007 Mikolaj Zalewski
+ * Copyright 2010 Adam Martinson for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -395,6 +396,8 @@ HRESULT queryresult_create(xmlNodePtr node, LPCWSTR szQuery, IXMLDOMNodeList **o
xmldoc_add_ref(This->node->doc);
ctxt->node = node;
+ registerNamespaces(ctxt);
+
This->result = xmlXPathEval(str, ctxt);
if (!This->result || This->result->type != XPATH_NODESET)
{
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 205716a..5ec0bc1 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -2998,7 +2998,7 @@ static void test_IXMLDOMDocument2(void)
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = SysAllocString(emptyW);
r = IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionNamespaces"), var);
- todo_wine ok(r == S_OK, "got 0x%08x\n", r);
+ ok(r == S_OK, "got 0x%08x\n", r);
VariantClear(&var);
V_VT(&var) = VT_I2;
@@ -3100,17 +3100,21 @@ static void test_XPath(void)
expect_list_and_release(list, "E3.E4.E2.D1");
/* it has to be declared in SelectionNamespaces */
- todo_wine ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
+ ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
_variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
/* now the namespace can be used */
- todo_wine ole_check(IXMLDOMDocument_selectNodes(doc, _bstr_("root//test:c"), &list));
- todo_wine expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
- todo_wine ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//test:c"), &list));
- todo_wine expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
- todo_wine ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//test:c"), &list));
- todo_wine expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
- todo_wine ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_(".//test:x"), &list));
+ ole_check(IXMLDOMDocument_selectNodes(doc, _bstr_("root//test:c"), &list));
+ expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
+ ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//test:c"), &list));
+ expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
+ ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//test:c"), &list));
+ expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
+ /* This one is failing due to not merging adjacent text nodes.
+ * At the line: "This is <strong>a</strong> <i>description</i>. <bar:x/>"
+ * "This is" is parsed as 1 node by native msxml3, and 2 nodes by our version.
+ * It selects the correct node, it just shows up as E6 instead of E5. */
+ ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_(".//test:x"), &list));
todo_wine expect_list_and_release(list, "E5.E1.E4.E1.E2.D1");
/* SelectionNamespaces syntax error - the namespaces doesn't work anymore but the value is stored */
@@ -3120,8 +3124,8 @@ static void test_XPath(void)
ole_expect(IXMLDOMDocument_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
VariantInit(&var);
- todo_wine ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
- todo_wine expect_eq(V_VT(&var), VT_BSTR, int, "%x");
+ ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
+ expect_eq(V_VT(&var), VT_BSTR, int, "%x");
if (V_VT(&var) == VT_BSTR)
expect_bstr_eq_and_free(V_BSTR(&var), "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###");
@@ -5763,7 +5767,7 @@ static void test_get_ownerDocument(void)
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = _bstr_("xmlns:wi=\'www.winehq.org\'");
hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), var);
- todo_wine ok( hr == S_OK, "got 0x%08x\n", hr);
+ ok( hr == S_OK, "got 0x%08x\n", hr);
hr = IXMLDOMDocument2_get_firstChild(doc, &node);
ok( hr == S_OK, "got 0x%08x\n", hr);
@@ -5771,13 +5775,13 @@ static void test_get_ownerDocument(void)
hr = IXMLDOMNode_get_ownerDocument(node, &doc1);
ok( hr == S_OK, "got 0x%08x\n", hr);
- VariantClear(&var);
hr = IXMLDOMDocument_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**)&doc_owner);
ok( hr == S_OK, "got 0x%08x\n", hr);
ok( doc_owner != doc, "got %p, doc %p\n", doc_owner, doc);
+
hr = IXMLDOMDocument2_getProperty(doc_owner, _bstr_("SelectionNamespaces"), &var);
- todo_wine ok( hr == S_OK, "got 0x%08x\n", hr);
- todo_wine ok( lstrcmpW(V_BSTR(&var), _bstr_("xmlns:wi=\'www.winehq.org\'")) == 0, "expected previously set value\n");
+ ok( hr == S_OK, "got 0x%08x\n", hr);
+ ok( lstrcmpW(V_BSTR(&var), _bstr_("xmlns:wi=\'www.winehq.org\'")) == 0, "expected previously set value\n");
VariantClear(&var);
hr = IXMLDOMDocument2_getProperty(doc_owner, _bstr_("SelectionLanguage"), &var);
@@ -5799,11 +5803,15 @@ static void test_get_ownerDocument(void)
ok( b == VARIANT_TRUE, "failed to load XML string\n");
SysFreeString( str );
- /* property retained even after reload */
- VariantClear(&var);
+ /* properties retained even after reload */
hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var);
- todo_wine ok( hr == S_OK, "got 0x%08x\n", hr);
- todo_wine ok( lstrcmpW(V_BSTR(&var), _bstr_("xmlns:wi=\'www.winehq.org\'")) == 0, "expected previously set value\n");
+ ok( hr == S_OK, "got 0x%08x\n", hr);
+ ok( lstrcmpW(V_BSTR(&var), _bstr_("xmlns:wi=\'www.winehq.org\'")) == 0, "expected previously set value\n");
+ VariantClear(&var);
+
+ hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &var);
+ ok( hr == S_OK, "got 0x%08x\n", hr);
+ ok( lstrcmpW(V_BSTR(&var), _bstr_("XPath")) == 0, "expected previously set value\n");
VariantClear(&var);
hr = IXMLDOMDocument2_get_firstChild(doc, &node);
--
1.7.2.3
More information about the wine-patches
mailing list