[MSXML3] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / reactos / dll / win32 / msxml3 / domdoc.c
index 15075e3..670741e 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#define WIN32_NO_STATUS
-#define _INC_WINDOWS
+#include "precomp.h"
 
-#define COBJMACROS
-#define NONAMELESSUNION
-
-#include <config.h>
-
-//#include <stdarg.h>
 #include <assert.h>
+
 #ifdef HAVE_LIBXML2
-# include <libxml/parser.h>
-//# include <libxml/xmlerror.h>
 # include <libxml/xpathInternals.h>
 # include <libxml/xmlsave.h>
 # include <libxml/SAX2.h>
 # include <libxml/parserInternals.h>
 #endif
 
-#include <windef.h>
-#include <winbase.h>
-//#include "winuser.h"
-//#include "winnls.h"
-#include <ole2.h>
 #include <olectl.h>
-#include <msxml6.h>
-//#include "wininet.h"
-//#include "winreg.h"
-//#include "shlwapi.h"
-//#include "ocidl.h"
 #include <objsafe.h>
 
-#include <wine/debug.h>
-#include <wine/list.h>
-
-#include "msxml_private.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(msxml);
-
 #ifdef HAVE_LIBXML2
 
 /* not defined in older versions */
@@ -89,6 +64,7 @@ typedef struct {
     xmlChar const* selectNsStr;
     LONG selectNsStr_len;
     BOOL XPath;
+    WCHAR *url;
 } domdoc_properties;
 
 typedef struct ConnectionPoint ConnectionPoint;
@@ -132,13 +108,9 @@ struct domdoc
     VARIANT_BOOL validating;
     VARIANT_BOOL resolving;
     domdoc_properties* properties;
-    bsc_t *bsc;
     HRESULT error;
 
-    /* IPersistStream */
-    IStream *stream;
-
-    /* IObjectWithSite*/
+    /* IObjectWithSite */
     IUnknown *site;
 
     /* IObjectSafety */
@@ -304,6 +276,9 @@ static domdoc_properties *create_properties(MSXML_VERSION version)
     properties->version = version;
     properties->XPath = (version == MSXML4 || version == MSXML6);
 
+    /* document url */
+    properties->url = NULL;
+
     return properties;
 }
 
@@ -338,6 +313,16 @@ static domdoc_properties* copy_properties(domdoc_properties const* properties)
             list_add_tail(&pcopy->selectNsList, &new_ns->entry);
         }
 
+        if (properties->url)
+        {
+            int len = strlenW(properties->url);
+
+            pcopy->url = CoTaskMemAlloc((len+1)*sizeof(WCHAR));
+            memcpy(pcopy->url, properties->url, len*sizeof(WCHAR));
+            pcopy->url[len] = 0;
+        }
+        else
+            pcopy->url = NULL;
     }
 
     return pcopy;
@@ -351,6 +336,7 @@ static void free_properties(domdoc_properties* properties)
             IXMLDOMSchemaCollection2_Release(properties->schemaCache);
         clear_selectNsList(&properties->selectNsList);
         heap_free((xmlChar*)properties->selectNsStr);
+        CoTaskMemFree(properties->url);
         heap_free(properties);
     }
 }
@@ -422,10 +408,26 @@ static void sax_characters(void *ctx, const xmlChar *ch, int len)
 
     if (ctxt->node)
     {
-        /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
+        xmlChar cur = *(ctxt->input->cur);
+
+        /* Characters are reported with multiple calls, for example each charref is reported with a separate
+           call and then parser appends it to a single text node or creates a new node if not created.
+           It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
+           space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
+           or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
+           contains text node pointer if already created, trailing spaces are detected directly looking at parser input
+           for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
+           chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
+           a text node it's safe to ignore.
+
+           Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
+
         if (!This->properties->preserving &&
             !is_preserving_whitespace(ctxt->node) &&
-            strn_isspace(ch, len))
+            strn_isspace(ch, len) &&
+            (!ctxt->node->last ||
+            ((ctxt->node->last && (cur == '<' || ctxt->node->last->type != XML_TEXT_NODE))
+           )))
             return;
     }
 
@@ -559,19 +561,28 @@ void xmldoc_init(xmlDocPtr doc, MSXML_VERSION version)
     priv_from_xmlDocPtr(doc)->properties = create_properties(version);
 }
 
-LONG xmldoc_add_ref(xmlDocPtr doc)
+LONG xmldoc_add_refs(xmlDocPtr doc, LONG refs)
 {
-    LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
+    LONG ref = InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc)->refs, refs) + refs;
     TRACE("(%p)->(%d)\n", doc, ref);
     return ref;
 }
 
-LONG xmldoc_release(xmlDocPtr doc)
+LONG xmldoc_add_ref(xmlDocPtr doc)
+{
+    return xmldoc_add_refs(doc, 1);
+}
+
+LONG xmldoc_release_refs(xmlDocPtr doc, LONG refs)
 {
     xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
-    LONG ref = InterlockedDecrement(&priv->refs);
+    LONG ref = InterlockedExchangeAdd(&priv->refs, -refs) - refs;
     TRACE("(%p)->(%d)\n", doc, ref);
-    if(ref == 0)
+
+    if (ref < 0)
+        WARN("negative refcount, expect troubles\n");
+
+    if (ref == 0)
     {
         orphan_entry *orphan, *orphan2;
         TRACE("freeing docptr %p\n", doc);
@@ -590,6 +601,11 @@ LONG xmldoc_release(xmlDocPtr doc)
     return ref;
 }
 
+LONG xmldoc_release(xmlDocPtr doc)
+{
+    return xmldoc_release_refs(doc, 1);
+}
+
 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
 {
     xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
@@ -624,7 +640,7 @@ HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
 
 static inline xmlDocPtr get_doc( domdoc *This )
 {
-    return (xmlDocPtr)This->node.node;
+    return This->node.node->doc;
 }
 
 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
@@ -721,46 +737,42 @@ static HRESULT WINAPI PersistStreamInit_IsDirty(
     return S_FALSE;
 }
 
-static HRESULT WINAPI PersistStreamInit_Load(
-    IPersistStreamInit *iface, LPSTREAM pStm)
+static HRESULT domdoc_load_from_stream(domdoc *doc, ISequentialStream *stream)
 {
-    domdoc *This = impl_from_IPersistStreamInit(iface);
-    HRESULT hr;
-    HGLOBAL hglobal;
     DWORD read, written, len;
+    xmlDocPtr xmldoc = NULL;
+    IStream *hstream;
+    HGLOBAL hglobal;
     BYTE buf[4096];
+    HRESULT hr;
     char *ptr;
-    xmlDocPtr xmldoc = NULL;
-
-    TRACE("(%p)->(%p)\n", This, pStm);
 
-    if (!pStm)
-        return E_INVALIDARG;
-
-    hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
+    hstream = NULL;
+    hr = CreateStreamOnHGlobal(NULL, TRUE, &hstream);
     if (FAILED(hr))
         return hr;
 
     do
     {
-        IStream_Read(pStm, buf, sizeof(buf), &read);
-        hr = IStream_Write(This->stream, buf, read, &written);
+        ISequentialStream_Read(stream, buf, sizeof(buf), &read);
+        hr = IStream_Write(hstream, buf, read, &written);
     } while(SUCCEEDED(hr) && written != 0 && read != 0);
 
     if (FAILED(hr))
     {
-        ERR("Failed to copy stream\n");
+        ERR("failed to copy stream 0x%08x\n", hr);
+        IStream_Release(hstream);
         return hr;
     }
 
-    hr = GetHGlobalFromStream(This->stream, &hglobal);
+    hr = GetHGlobalFromStream(hstream, &hglobal);
     if (FAILED(hr))
         return hr;
 
     len = GlobalSize(hglobal);
     ptr = GlobalLock(hglobal);
-    if (len != 0)
-        xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
+    if (len)
+        xmldoc = doparse(doc, ptr, len, XML_CHAR_ENCODING_NONE);
     GlobalUnlock(hglobal);
 
     if (!xmldoc)
@@ -771,7 +783,19 @@ static HRESULT WINAPI PersistStreamInit_Load(
 
     xmldoc->_private = create_priv();
 
-    return attach_xmldoc(This, xmldoc);
+    return attach_xmldoc(doc, xmldoc);
+}
+
+static HRESULT WINAPI PersistStreamInit_Load(IPersistStreamInit *iface, IStream *stream)
+{
+    domdoc *This = impl_from_IPersistStreamInit(iface);
+
+    TRACE("(%p)->(%p)\n", This, stream);
+
+    if (!stream)
+        return E_INVALIDARG;
+
+    return domdoc_load_from_stream(This, (ISequentialStream*)stream);
 }
 
 static HRESULT WINAPI PersistStreamInit_Save(
@@ -801,7 +825,7 @@ static HRESULT WINAPI PersistStreamInit_GetSizeMax(
     IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
 {
     domdoc *This = impl_from_IPersistStreamInit(iface);
-    TRACE("(%p)->(%p): stub!\n", This, pcbSize);
+    TRACE("(%p)->(%p)\n", This, pcbSize);
     return E_NOTIMPL;
 }
 
@@ -833,7 +857,7 @@ static const tid_t domdoc_se_tids[] = {
     IXMLDOMDocument_tid,
     IXMLDOMDocument2_tid,
     IXMLDOMDocument3_tid,
-    0
+    NULL_tid
 };
 
 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
@@ -908,14 +932,9 @@ static ULONG WINAPI domdoc_Release( IXMLDOMDocument3 *iface )
     {
         int eid;
 
-        if(This->bsc)
-            detach_bsc(This->bsc);
-
         if (This->site)
             IUnknown_Release( This->site );
         destroy_xmlnode(&This->node);
-        if (This->stream)
-            IStream_Release(This->stream);
 
         for (eid = 0; eid < EVENTID_LAST; eid++)
             if (This->events[eid]) IDispatch_Release(This->events[eid]);
@@ -1115,12 +1134,26 @@ static HRESULT WINAPI domdoc_insertBefore(
     IXMLDOMNode** outNewChild )
 {
     domdoc *This = impl_from_IXMLDOMDocument3( iface );
+    DOMNodeType type;
+    HRESULT hr;
 
     TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), outNewChild);
 
-    return node_insert_before(&This->node, newChild, &refChild, outNewChild);
-}
+    hr = IXMLDOMNode_get_nodeType(newChild, &type);
+    if (hr != S_OK) return hr;
 
+    TRACE("new node type %d\n", type);
+    switch (type)
+    {
+        case NODE_ATTRIBUTE:
+        case NODE_DOCUMENT:
+        case NODE_CDATA_SECTION:
+            if (outNewChild) *outNewChild = NULL;
+            return E_FAIL;
+        default:
+            return node_insert_before(&This->node, newChild, &refChild, outNewChild);
+    }
+}
 
 static HRESULT WINAPI domdoc_replaceChild(
     IXMLDOMDocument3 *iface,
@@ -1510,7 +1543,9 @@ static HRESULT WINAPI domdoc_put_documentElement(
     domdoc *This = impl_from_IXMLDOMDocument3( iface );
     IXMLDOMNode *elementNode;
     xmlNodePtr oldRoot;
+    xmlDocPtr old_doc;
     xmlnode *xmlNode;
+    int refcount = 0;
     HRESULT hr;
 
     TRACE("(%p)->(%p)\n", This, DOMElement);
@@ -1526,7 +1561,14 @@ static HRESULT WINAPI domdoc_put_documentElement(
         if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
             WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
 
+    old_doc = xmlNode->node->doc;
+    if (old_doc != get_doc(This))
+        refcount = xmlnode_get_inst_cnt(xmlNode);
+
+    /* old root is still orphaned by its document, update refcount from new root */
+    if (refcount) xmldoc_add_refs(get_doc(This), refcount);
     oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
+    if (refcount) xmldoc_release_refs(old_doc, refcount);
     IXMLDOMNode_Release( elementNode );
 
     if(oldRoot)
@@ -1783,12 +1825,18 @@ static HRESULT WINAPI domdoc_createEntityReference(
 xmlChar* tagName_to_XPath(const BSTR tagName)
 {
     xmlChar *query, *tmp;
+    static const xmlChar everything[] = "/descendant::node()";
     static const xmlChar mod_pre[] = "*[local-name()='";
     static const xmlChar mod_post[] = "']";
     static const xmlChar prefix[] = "descendant::";
     const WCHAR *tokBegin, *tokEnd;
     int len;
 
+    /* Special case - empty tagname - means select all nodes,
+       except document itself. */
+    if (!*tagName)
+        return xmlStrdup(everything);
+
     query = xmlStrdup(prefix);
 
     tokBegin = tagName;
@@ -1881,9 +1929,6 @@ static HRESULT WINAPI domdoc_createNode(
     hr = get_node_type(Type, &node_type);
     if(FAILED(hr)) return hr;
 
-    if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
-        FIXME("nodes with namespaces currently not supported.\n");
-
     TRACE("node_type %d\n", node_type);
 
     /* exit earlier for types that need name */
@@ -1900,7 +1945,7 @@ static HRESULT WINAPI domdoc_createNode(
     }
 
     xml_name = xmlchar_from_wchar(name);
-    /* prevent empty href to be allocated */
+    /* prevent empty href from being allocated */
     href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
 
     switch(node_type)
@@ -1913,7 +1958,7 @@ static HRESULT WINAPI domdoc_createNode(
 
         xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
 
-        /* allow to create default namespace xmlns= */
+        /* allow creating the default namespace xmlns= */
         if (local || (href && *href))
         {
             xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
@@ -1926,8 +1971,26 @@ static HRESULT WINAPI domdoc_createNode(
         break;
     }
     case NODE_ATTRIBUTE:
-        xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
+    {
+        xmlChar *local, *prefix;
+
+        local = xmlSplitQName2(xml_name, &prefix);
+
+        xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), local ? local : xml_name, NULL);
+
+        if (local || (href && *href))
+        {
+            /* we need a floating namespace here, it can't be created linked to attribute from
+               a start */
+            xmlNsPtr ns = xmlNewNs(NULL, href, prefix);
+            xmlSetNs(xmlnode, ns);
+        }
+
+        xmlFree(local);
+        xmlFree(prefix);
+
         break;
+    }
     case NODE_TEXT:
         xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
         break;
@@ -1999,7 +2062,7 @@ static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
         return attach_xmldoc(This, xmldoc);
     }
 
-    return S_OK;
+    return E_FAIL;
 }
 
 static HRESULT domdoc_load_moniker(domdoc *This, IMoniker *mon)
@@ -2011,14 +2074,7 @@ static HRESULT domdoc_load_moniker(domdoc *This, IMoniker *mon)
     if(FAILED(hr))
         return hr;
 
-    if(This->bsc) {
-        hr = detach_bsc(This->bsc);
-        if(FAILED(hr))
-            return hr;
-    }
-
-    This->bsc = bsc;
-    return S_OK;
+    return detach_bsc(bsc);
 }
 
 static HRESULT WINAPI domdoc_load(
@@ -2029,8 +2085,6 @@ static HRESULT WINAPI domdoc_load(
     domdoc *This = impl_from_IXMLDOMDocument3( iface );
     LPWSTR filename = NULL;
     HRESULT hr = S_FALSE;
-    IXMLDOMDocument3 *pNewDoc = NULL;
-    IStream *pStream = NULL;
     xmlDocPtr xmldoc;
 
     TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
@@ -2066,7 +2120,13 @@ static HRESULT WINAPI domdoc_load(
             case 1:
                 /* Only takes UTF-8 strings.
                  * NOT NULL-terminated. */
-                SafeArrayAccessData(psa, (void**)&str);
+                hr = SafeArrayAccessData(psa, (void**)&str);
+                if (FAILED(hr))
+                {
+                    This->error = hr;
+                    WARN("failed to access array data, 0x%08x\n", hr);
+                    break;
+                }
                 SafeArrayGetUBound(psa, 1, &len);
 
                 if ((xmldoc = doparse(This, str, ++len, XML_CHAR_ENCODING_UTF8)))
@@ -2096,13 +2156,18 @@ static HRESULT WINAPI domdoc_load(
         }
         break;
     case VT_UNKNOWN:
+    {
+        ISequentialStream *stream = NULL;
+        IXMLDOMDocument3 *newdoc = NULL;
+
         if (!V_UNKNOWN(&source)) return E_INVALIDARG;
-        hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
+
+        hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&newdoc);
         if(hr == S_OK)
         {
-            if(pNewDoc)
+            if(newdoc)
             {
-                domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
+                domdoc *newDoc = impl_from_IXMLDOMDocument3( newdoc );
 
                 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
                 xmldoc->_private = create_priv();
@@ -2114,50 +2179,40 @@ static HRESULT WINAPI domdoc_load(
                 return hr;
             }
         }
-        hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&pStream);
-        if(hr == S_OK)
-        {
-            IPersistStream *pDocStream;
-            hr = IXMLDOMDocument3_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
-            if(hr == S_OK)
-            {
-                hr = IPersistStream_Load(pDocStream, pStream);
-                IStream_Release(pStream);
-                if(hr == S_OK)
-                {
-                    *isSuccessful = VARIANT_TRUE;
 
-                    TRACE("Using IStream to load Document\n");
-                    return S_OK;
-                }
-                else
-                {
-                    ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
-                }
-            }
-            else
-            {
-                ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
-            }
-        }
-        else
+        hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&stream);
+        if (FAILED(hr))
+            hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_ISequentialStream, (void**)&stream);
+
+        if (hr == S_OK)
         {
-            /* ISequentialStream */
-            FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl);
+            hr = domdoc_load_from_stream(This, stream);
+            if (hr == S_OK)
+                *isSuccessful = VARIANT_TRUE;
+            ISequentialStream_Release(stream);
+            return hr;
         }
+
+        FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr, V_UNKNOWN(&source)->lpVtbl);
         break;
-     default:
-            FIXME("VT type not supported (%d)\n", V_VT(&source));
+    }
+    default:
+        FIXME("VT type not supported (%d)\n", V_VT(&source));
     }
 
     if ( filename )
     {
         IMoniker *mon;
 
+        CoTaskMemFree(This->properties->url);
+        This->properties->url = NULL;
+
         hr = create_moniker_from_url( filename, &mon);
         if ( SUCCEEDED(hr) )
         {
             hr = domdoc_load_moniker( This, mon );
+            if (hr == S_OK)
+                IMoniker_GetDisplayName(mon, NULL, NULL, &This->properties->url);
             IMoniker_Release(mon);
         }
 
@@ -2220,11 +2275,25 @@ static HRESULT WINAPI domdoc_get_parseError(
 
 static HRESULT WINAPI domdoc_get_url(
     IXMLDOMDocument3 *iface,
-    BSTR* urlString )
+    BSTR* url )
 {
     domdoc *This = impl_from_IXMLDOMDocument3(iface);
-    FIXME("(%p)->(%p)\n", This, urlString);
-    return E_NOTIMPL;
+
+    TRACE("(%p)->(%p)\n", This, url);
+
+    if (!url)
+        return E_INVALIDARG;
+
+    if (This->properties->url)
+    {
+        *url = SysAllocString(This->properties->url);
+        if (!*url)
+            return E_OUTOFMEMORY;
+
+        return S_OK;
+    }
+    else
+        return return_null_bstr(url);
 }
 
 
@@ -2547,7 +2616,7 @@ static HRESULT WINAPI domdoc_get_namespaces(
 
     if (!This->namespaces)
     {
-        hr = SchemaCache_create(This->properties->version, NULL, (void**)&This->namespaces);
+        hr = SchemaCache_create(This->properties->version, (void**)&This->namespaces);
         if (hr != S_OK) return hr;
 
         hr = cache_from_doc_ns(This->namespaces, &This->node);
@@ -2956,7 +3025,7 @@ static HRESULT WINAPI domdoc_setProperty(
              lstrcmpiW(p, PropertyResolveExternalsW) == 0)
     {
         /* Ignore */
-        FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&value));
+        FIXME("Ignoring property %s, value %s\n", debugstr_w(p), debugstr_variant(&value));
         return S_OK;
     }
 
@@ -3251,12 +3320,43 @@ static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoi
     return S_OK;
 }
 
-static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
-                                             DWORD *pdwCookie)
+static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *unk_sink,
+                                             DWORD *cookie)
 {
     ConnectionPoint *This = impl_from_IConnectionPoint(iface);
-    FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
-    return E_NOTIMPL;
+    IUnknown *sink;
+    HRESULT hr;
+    DWORD i;
+
+    TRACE("(%p)->(%p %p)\n", This, unk_sink, cookie);
+
+    hr = IUnknown_QueryInterface(unk_sink, This->iid, (void**)&sink);
+    if(FAILED(hr) && !IsEqualGUID(&IID_IPropertyNotifySink, This->iid))
+        hr = IUnknown_QueryInterface(unk_sink, &IID_IDispatch, (void**)&sink);
+    if(FAILED(hr))
+        return CONNECT_E_CANNOTCONNECT;
+
+    if(This->sinks)
+    {
+        for (i = 0; i < This->sinks_size; i++)
+            if (!This->sinks[i].unk)
+                break;
+
+        if (i == This->sinks_size)
+            This->sinks = heap_realloc(This->sinks,(++This->sinks_size)*sizeof(*This->sinks));
+    }
+    else
+    {
+        This->sinks = heap_alloc(sizeof(*This->sinks));
+        This->sinks_size = 1;
+        i = 0;
+    }
+
+    This->sinks[i].unk = sink;
+    if (cookie)
+        *cookie = i+1;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
@@ -3466,10 +3566,8 @@ HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
     doc->resolving = 0;
     doc->properties = properties_from_xmlDocPtr(xmldoc);
     doc->error = S_OK;
-    doc->stream = NULL;
     doc->site = NULL;
     doc->safeopt = 0;
-    doc->bsc = NULL;
     doc->cp_list = NULL;
     doc->namespaces = NULL;
     memset(doc->events, 0, sizeof(doc->events));
@@ -3488,12 +3586,12 @@ HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
     return S_OK;
 }
 
-HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
+HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
 {
     xmlDocPtr xmldoc;
     HRESULT hr;
 
-    TRACE("(%d, %p, %p)\n", version, pUnkOuter, ppObj);
+    TRACE("(%d, %p)\n", version, ppObj);
 
     xmldoc = xmlNewDoc(NULL);
     if(!xmldoc)
@@ -3529,7 +3627,7 @@ IUnknown* create_domdoc( xmlNodePtr document )
 
 #else
 
-HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
+HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
 {
     MESSAGE("This program tried to use a DOMDocument object, but\n"
             "libxml2 support was not present at compile time.\n");