>From f7b41bfecc73766ce85fd277a7c02e0ceffc1da1 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Fri, 4 Nov 2011 11:46:45 +0300
Subject: [PATCH 1/4] Fix IDispatch support for IXMLDocument

---
 dlls/msxml3/dispex.c       |  129 ++++++++++++++++++++++++++-----------------
 dlls/msxml3/tests/xmldoc.c |   62 ++++++++++++---------
 dlls/msxml3/xmldoc.c       |   21 +++----
 3 files changed, 122 insertions(+), 90 deletions(-)

diff --git a/dlls/msxml3/dispex.c b/dlls/msxml3/dispex.c
index 67ce77c..ae84ab9 100644
--- a/dlls/msxml3/dispex.c
+++ b/dlls/msxml3/dispex.c
@@ -45,6 +45,23 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
 
+enum lib_version_t
+{
+    LibXml = 0,
+    LibXml2,
+    LibXml_Last
+};
+
+typedef struct {
+    REFIID iid;
+    enum lib_version_t lib;
+} tid_id_t;
+
+typedef struct {
+    REFIID iid;
+    unsigned short major;
+} lib_id_t;
+
 typedef struct {
     DISPID id;
     BSTR name;
@@ -74,74 +91,85 @@ struct dispex_dynamic_data_t {
 #define DISPID_DYNPROP_MAX  0x5fffffff
 
 static struct list dispex_data_list = LIST_INIT(dispex_data_list);
-static ITypeLib *typelib;
+static ITypeLib *typelib[LibXml_Last];
 static ITypeInfo *typeinfos[LAST_tid];
 
-static REFIID tid_ids[] = {
-    &IID_NULL,
-    &IID_IXMLDOMAttribute,
-    &IID_IXMLDOMCDATASection,
-    &IID_IXMLDOMComment,
-    &IID_IXMLDOMDocument,
-    &IID_IXMLDOMDocument2,
-    &IID_IXMLDOMDocumentFragment,
-    &IID_IXMLDOMDocumentType,
-    &IID_IXMLDOMElement,
-    &IID_IXMLDOMEntityReference,
-    &IID_IXMLDOMImplementation,
-    &IID_IXMLDOMNamedNodeMap,
-    &IID_IXMLDOMNode,
-    &IID_IXMLDOMNodeList,
-    &IID_IXMLDOMParseError,
-    &IID_IXMLDOMProcessingInstruction,
-    &IID_IXMLDOMSchemaCollection,
-    &IID_IXMLDOMSelection,
-    &IID_IXMLDOMText,
-    &IID_IXMLElement,
-    &IID_IXMLDOMDocument,
-    &IID_IXMLHTTPRequest,
-    &IID_IXSLProcessor,
-    &IID_IXSLTemplate,
-    &IID_IVBSAXAttributes,
-    &IID_IVBSAXContentHandler,
-    &IID_IVBSAXDeclHandler,
-    &IID_IVBSAXDTDHandler,
-    &IID_IVBSAXEntityResolver,
-    &IID_IVBSAXErrorHandler,
-    &IID_IVBSAXLexicalHandler,
-    &IID_IVBSAXLocator,
-    &IID_IVBSAXXMLFilter,
-    &IID_IVBSAXXMLReader,
-    &IID_IMXAttributes,
-    &IID_IMXReaderControl,
-    &IID_IMXWriter,
-    &IID_IVBMXNamespaceManager
+/* indexed with lib_version_t values */
+static lib_id_t lib_ids[] = {
+    { &LIBID_MSXML,  2 },
+    { &LIBID_MSXML2, 3 }
+};
+
+static tid_id_t tid_ids[] = {
+    { &IID_NULL, LibXml_Last },
+    { &IID_IXMLDOMAttribute, LibXml2 },
+    { &IID_IXMLDOMCDATASection, LibXml2 },
+    { &IID_IXMLDOMComment, LibXml2 },
+    { &IID_IXMLDOMDocument, LibXml2 },
+    { &IID_IXMLDOMDocument2, LibXml2 },
+    { &IID_IXMLDOMDocumentFragment, LibXml2 },
+    { &IID_IXMLDOMDocumentType, LibXml2 },
+    { &IID_IXMLDOMElement, LibXml2 },
+    { &IID_IXMLDOMEntityReference, LibXml2 },
+    { &IID_IXMLDOMImplementation, LibXml2 },
+    { &IID_IXMLDOMNamedNodeMap, LibXml2 },
+    { &IID_IXMLDOMNode, LibXml2 },
+    { &IID_IXMLDOMNodeList, LibXml2 },
+    { &IID_IXMLDOMParseError, LibXml2 },
+    { &IID_IXMLDOMProcessingInstruction, LibXml2 },
+    { &IID_IXMLDOMSchemaCollection, LibXml2 },
+    { &IID_IXMLDOMSelection, LibXml2 },
+    { &IID_IXMLDOMText, LibXml2 },
+    { &IID_IXMLElement, LibXml },
+    { &IID_IXMLDocument, LibXml },
+    { &IID_IXMLHTTPRequest, LibXml2 },
+    { &IID_IXSLProcessor, LibXml2 },
+    { &IID_IXSLTemplate, LibXml2 },
+    { &IID_IVBSAXAttributes, LibXml2 },
+    { &IID_IVBSAXContentHandler, LibXml2 },
+    { &IID_IVBSAXDeclHandler, LibXml2 },
+    { &IID_IVBSAXDTDHandler, LibXml2 },
+    { &IID_IVBSAXEntityResolver, LibXml2 },
+    { &IID_IVBSAXErrorHandler, LibXml2 },
+    { &IID_IVBSAXLexicalHandler, LibXml2 },
+    { &IID_IVBSAXLocator, LibXml2 },
+    { &IID_IVBSAXXMLFilter, LibXml2 },
+    { &IID_IVBSAXXMLReader, LibXml2 },
+    { &IID_IMXAttributes, LibXml2 },
+    { &IID_IMXReaderControl, LibXml2 },
+    { &IID_IMXWriter, LibXml2 },
+    { &IID_IVBMXNamespaceManager, LibXml2 }
 };
 
 HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo)
 {
+    unsigned lib = tid_ids[tid].lib;
     HRESULT hres;
 
-    if(!typelib) {
+    if(!typelib[lib]) {
         ITypeLib *tl;
 
-        hres = LoadRegTypeLib(&LIBID_MSXML2, 3, 0, LOCALE_SYSTEM_DEFAULT, &tl);
+        hres = LoadRegTypeLib(lib_ids[lib].iid, lib_ids[lib].major, 0, LOCALE_SYSTEM_DEFAULT, &tl);
         if(FAILED(hres)) {
             ERR("LoadRegTypeLib failed: %08x\n", hres);
             return hres;
         }
 
-        if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
+        if(InterlockedCompareExchangePointer((void**)&typelib[lib], tl, NULL))
             ITypeLib_Release(tl);
     }
 
     if(!typeinfos[tid]) {
         ITypeInfo *ti;
 
-        hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
+        hres = ITypeLib_GetTypeInfoOfGuid(typelib[lib], tid_ids[tid].iid, &ti);
         if(FAILED(hres)) {
-            ERR("GetTypeInfoOfGuid failed: %08x\n", hres);
-            return hres;
+            /* try harder with typelib from msxml.dll */
+            hres = ITypeLib_GetTypeInfoOfGuid(typelib[LibXml], tid_ids[tid].iid, &ti);
+            if(FAILED(hres)) {
+                ERR("GetTypeInfoOfGuid failed: %08x\n", hres);
+                return hres;
+            }
         }
 
         if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
@@ -171,14 +199,13 @@ void release_typelib(void)
         heap_free(iter);
     }
 
-    if(!typelib)
-        return;
-
     for(i=0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++)
         if(typeinfos[i])
             ITypeInfo_Release(typeinfos[i]);
 
-    ITypeLib_Release(typelib);
+    for(i=0; i < sizeof(typelib)/sizeof(*typelib); i++)
+        if(typelib[i])
+            ITypeLib_Release(typelib[i]);
 }
 
 static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, DISPID id, ITypeInfo *dti)
@@ -555,7 +582,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
         return hres;
     }
 
-    hres = IUnknown_QueryInterface(This->outer, tid_ids[data->funcs[n].tid], (void**)&unk);
+    hres = IUnknown_QueryInterface(This->outer, tid_ids[data->funcs[n].tid].iid, (void**)&unk);
     if(FAILED(hres)) {
         ERR("Could not get iface: %08x\n", hres);
         return E_FAIL;
diff --git a/dlls/msxml3/tests/xmldoc.c b/dlls/msxml3/tests/xmldoc.c
index 476924c..d2828db 100644
--- a/dlls/msxml3/tests/xmldoc.c
+++ b/dlls/msxml3/tests/xmldoc.c
@@ -24,10 +24,14 @@
 #include "windows.h"
 #include "ole2.h"
 #include "msxml2.h"
+#include "msxml2did.h"
 #include "ocidl.h"
 
 #include "wine/test.h"
 
+#define EXPECT_HR(hr,hr_exp) \
+    ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
+
 /* Deprecated Error Code */
 #define XML_E_INVALIDATROOTLEVEL    0xc00ce556
 
@@ -49,25 +53,6 @@ static void create_xml_file(LPCSTR filename)
     CloseHandle(hf);
 }
 
-/*
-static void create_xml_file(LPCSTR filename)
-{
-    DWORD dwNumberOfBytesWritten;
-    HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
-                           CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-
-    static const char data[] =
-        "<?xml version=\"1.0\" ?>\n"
-        "<BankAccount>\n"
-        "  <Number>1234</Number>\n"
-        "  <Name>Captain Ahab</Name>\n"
-        "</BankAccount>\n";
-
-    WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
-    CloseHandle(hf);
-}
-*/
-
 static void create_stream_on_file(IStream **stream, LPCSTR path)
 {
     HANDLE hfile;
@@ -97,16 +82,18 @@ static void create_stream_on_file(IStream **stream, LPCSTR path)
 
 static void test_xmldoc(void)
 {
-    HRESULT hr;
-    IXMLDocument *doc = NULL;
     IXMLElement *element = NULL, *child = NULL, *value = NULL;
     IXMLElementCollection *collection = NULL, *inner = NULL;
     IPersistStreamInit *psi = NULL;
+    IXMLDocument *doc = NULL;
     IStream *stream = NULL;
-    CHAR path[MAX_PATH];
-    LONG type, num_child;
     VARIANT vIndex, vName;
-    BSTR name = NULL;
+    LONG type, num_child;
+    CHAR path[MAX_PATH];
+    IDispatch *disp;
+    ITypeInfo *ti;
+    HRESULT hr;
+    BSTR name;
 
     static const WCHAR szBankAccount[] = {'B','A','N','K','A','C','C','O','U','N','T',0};
     static const WCHAR szNumber[] = {'N','U','M','B','E','R',0};
@@ -114,16 +101,36 @@ static void test_xmldoc(void)
     static const WCHAR szName[] = {'N','A','M','E',0};
     static const WCHAR szNameVal[] = {'C','a','p','t','a','i','n',' ','A','h','a','b',0};
     static const WCHAR szVersion[] = {'1','.','0',0};
+    static const WCHAR rootW[] = {'r','o','o','t',0};
 
     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
-                          &IID_IXMLDocument, (LPVOID*)&doc);
-    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+                          &IID_IXMLDocument, (void**)&doc);
+    EXPECT_HR(hr, S_OK);
+
+    /* IDispatch */
+    hr = IXMLDocument_QueryInterface(doc, &IID_IDispatch, (void**)&disp);
+    EXPECT_HR(hr, S_OK);
+
+    /* just to make sure we're on right type data */
+    hr = IDispatch_GetTypeInfo(disp, 0, 0, &ti);
+    EXPECT_HR(hr, S_OK);
+    name = NULL;
+    hr = ITypeInfo_GetDocumentation(ti, DISPID_XMLDOCUMENT_ROOT, &name, NULL, NULL, NULL);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(name, rootW), "got name %s\n", wine_dbgstr_w(name));
+    SysFreeString(name);
+
+    ITypeInfo_Release(ti);
+    IDispatch_Release(disp);
+
+    hr = IXMLDocument_QueryInterface(doc, &IID_IXMLDOMDocument, (void**)&disp);
+    EXPECT_HR(hr, E_NOINTERFACE);
 
     create_xml_file("bank.xml");
     GetFullPathNameA("bank.xml", MAX_PATH, path, NULL);
     create_stream_on_file(&stream, path);
 
-    hr = IXMLDocument_QueryInterface(doc, &IID_IPersistStreamInit, (LPVOID *)&psi);
+    hr = IXMLDocument_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&psi);
     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
     ok(psi != NULL, "Expected non-NULL psi\n");
 
@@ -142,6 +149,7 @@ static void test_xmldoc(void)
     hr = IXMLDocument_get_version(doc, NULL);
     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
 
+    name = NULL;
     hr = IXMLDocument_get_version(doc, &name);
     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
     ok(!lstrcmpW(name, szVersion), "Expected 1.0, got %s\n", wine_dbgstr_w(name));
diff --git a/dlls/msxml3/xmldoc.c b/dlls/msxml3/xmldoc.c
index a9d1dd8..1cf8785 100644
--- a/dlls/msxml3/xmldoc.c
+++ b/dlls/msxml3/xmldoc.c
@@ -81,9 +81,9 @@ static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, vo
 
     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
 
-    if (IsEqualGUID(riid, &IID_IUnknown) ||
-        IsEqualGUID(riid, &IID_IXMLDocument) ||
-        IsEqualGUID(riid, &IID_IXMLDOMDocument))
+    if (IsEqualGUID(riid, &IID_IUnknown)  ||
+        IsEqualGUID(riid, &IID_IDispatch) ||
+        IsEqualGUID(riid, &IID_IXMLDocument))
     {
         *ppvObject = iface;
     }
@@ -107,18 +107,18 @@ static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, vo
 static ULONG WINAPI xmldoc_AddRef(IXMLDocument *iface)
 {
     xmldoc *This = impl_from_IXMLDocument(iface);
-    TRACE("%p\n", This);
-    return InterlockedIncrement(&This->ref);
+    ULONG ref = InterlockedIncrement(&This->ref);
+    TRACE("(%p)->(%d)\n", This, ref);
+    return ref;
 }
 
 static ULONG WINAPI xmldoc_Release(IXMLDocument *iface)
 {
     xmldoc *This = impl_from_IXMLDocument(iface);
-    LONG ref;
+    LONG ref = InterlockedDecrement(&This->ref);
 
-    TRACE("%p\n", This);
+    TRACE("(%p)->(%d)\n", This, ref);
 
-    ref = InterlockedDecrement(&This->ref);
     if (ref == 0)
     {
         xmlFreeDoc(This->xmldoc);
@@ -144,13 +144,10 @@ static HRESULT WINAPI xmldoc_GetTypeInfo(IXMLDocument *iface, UINT iTInfo,
                                          LCID lcid, ITypeInfo** ppTInfo)
 {
     xmldoc *This = impl_from_IXMLDocument(iface);
-    HRESULT hr;
 
     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
 
-    hr = get_typeinfo(IXMLDocument_tid, ppTInfo);
-
-    return hr;
+    return get_typeinfo(IXMLDocument_tid, ppTInfo);
 }
 
 static HRESULT WINAPI xmldoc_GetIDsOfNames(IXMLDocument *iface, REFIID riid,
-- 
1.5.6.5


