Commit c32db174 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

msxml3: Fix IDispatch support for IXMLDocument.

parent 08a4ca7b
...@@ -45,6 +45,23 @@ ...@@ -45,6 +45,23 @@
WINE_DEFAULT_DEBUG_CHANNEL(msxml); 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 { typedef struct {
DISPID id; DISPID id;
BSTR name; BSTR name;
...@@ -74,75 +91,86 @@ struct dispex_dynamic_data_t { ...@@ -74,75 +91,86 @@ struct dispex_dynamic_data_t {
#define DISPID_DYNPROP_MAX 0x5fffffff #define DISPID_DYNPROP_MAX 0x5fffffff
static struct list dispex_data_list = LIST_INIT(dispex_data_list); 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 ITypeInfo *typeinfos[LAST_tid];
static REFIID tid_ids[] = { /* indexed with lib_version_t values */
&IID_NULL, static lib_id_t lib_ids[] = {
&IID_IXMLDOMAttribute, { &LIBID_MSXML, 2 },
&IID_IXMLDOMCDATASection, { &LIBID_MSXML2, 3 }
&IID_IXMLDOMComment, };
&IID_IXMLDOMDocument,
&IID_IXMLDOMDocument2, static tid_id_t tid_ids[] = {
&IID_IXMLDOMDocumentFragment, { &IID_NULL, LibXml_Last },
&IID_IXMLDOMDocumentType, { &IID_IXMLDOMAttribute, LibXml2 },
&IID_IXMLDOMElement, { &IID_IXMLDOMCDATASection, LibXml2 },
&IID_IXMLDOMEntityReference, { &IID_IXMLDOMComment, LibXml2 },
&IID_IXMLDOMImplementation, { &IID_IXMLDOMDocument, LibXml2 },
&IID_IXMLDOMNamedNodeMap, { &IID_IXMLDOMDocument2, LibXml2 },
&IID_IXMLDOMNode, { &IID_IXMLDOMDocumentFragment, LibXml2 },
&IID_IXMLDOMNodeList, { &IID_IXMLDOMDocumentType, LibXml2 },
&IID_IXMLDOMParseError, { &IID_IXMLDOMElement, LibXml2 },
&IID_IXMLDOMProcessingInstruction, { &IID_IXMLDOMEntityReference, LibXml2 },
&IID_IXMLDOMSchemaCollection, { &IID_IXMLDOMImplementation, LibXml2 },
&IID_IXMLDOMSelection, { &IID_IXMLDOMNamedNodeMap, LibXml2 },
&IID_IXMLDOMText, { &IID_IXMLDOMNode, LibXml2 },
&IID_IXMLElement, { &IID_IXMLDOMNodeList, LibXml2 },
&IID_IXMLDOMDocument, { &IID_IXMLDOMParseError, LibXml2 },
&IID_IXMLHTTPRequest, { &IID_IXMLDOMProcessingInstruction, LibXml2 },
&IID_IXSLProcessor, { &IID_IXMLDOMSchemaCollection, LibXml2 },
&IID_IXSLTemplate, { &IID_IXMLDOMSelection, LibXml2 },
&IID_IVBSAXAttributes, { &IID_IXMLDOMText, LibXml2 },
&IID_IVBSAXContentHandler, { &IID_IXMLElement, LibXml },
&IID_IVBSAXDeclHandler, { &IID_IXMLDocument, LibXml },
&IID_IVBSAXDTDHandler, { &IID_IXMLHTTPRequest, LibXml2 },
&IID_IVBSAXEntityResolver, { &IID_IXSLProcessor, LibXml2 },
&IID_IVBSAXErrorHandler, { &IID_IXSLTemplate, LibXml2 },
&IID_IVBSAXLexicalHandler, { &IID_IVBSAXAttributes, LibXml2 },
&IID_IVBSAXLocator, { &IID_IVBSAXContentHandler, LibXml2 },
&IID_IVBSAXXMLFilter, { &IID_IVBSAXDeclHandler, LibXml2 },
&IID_IVBSAXXMLReader, { &IID_IVBSAXDTDHandler, LibXml2 },
&IID_IMXAttributes, { &IID_IVBSAXEntityResolver, LibXml2 },
&IID_IMXReaderControl, { &IID_IVBSAXErrorHandler, LibXml2 },
&IID_IMXWriter, { &IID_IVBSAXLexicalHandler, LibXml2 },
&IID_IVBMXNamespaceManager { &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) HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo)
{ {
unsigned lib = tid_ids[tid].lib;
HRESULT hres; HRESULT hres;
if(!typelib) { if(!typelib[lib]) {
ITypeLib *tl; 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)) { if(FAILED(hres)) {
ERR("LoadRegTypeLib failed: %08x\n", hres); ERR("LoadRegTypeLib failed: %08x\n", hres);
return hres; return hres;
} }
if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL)) if(InterlockedCompareExchangePointer((void**)&typelib[lib], tl, NULL))
ITypeLib_Release(tl); ITypeLib_Release(tl);
} }
if(!typeinfos[tid]) { if(!typeinfos[tid]) {
ITypeInfo *ti; ITypeInfo *ti;
hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti); hres = ITypeLib_GetTypeInfoOfGuid(typelib[lib], tid_ids[tid].iid, &ti);
if(FAILED(hres)) {
/* try harder with typelib from msxml.dll */
hres = ITypeLib_GetTypeInfoOfGuid(typelib[LibXml], tid_ids[tid].iid, &ti);
if(FAILED(hres)) { if(FAILED(hres)) {
ERR("GetTypeInfoOfGuid failed: %08x\n", hres); ERR("GetTypeInfoOfGuid failed: %08x\n", hres);
return hres; return hres;
} }
}
if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL)) if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
ITypeInfo_Release(ti); ITypeInfo_Release(ti);
...@@ -171,14 +199,13 @@ void release_typelib(void) ...@@ -171,14 +199,13 @@ void release_typelib(void)
heap_free(iter); heap_free(iter);
} }
if(!typelib)
return;
for(i=0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++) for(i=0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++)
if(typeinfos[i]) if(typeinfos[i])
ITypeInfo_Release(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) 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 ...@@ -555,7 +582,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
return hres; 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)) { if(FAILED(hres)) {
ERR("Could not get iface: %08x\n", hres); ERR("Could not get iface: %08x\n", hres);
return E_FAIL; return E_FAIL;
......
...@@ -24,10 +24,14 @@ ...@@ -24,10 +24,14 @@
#include "windows.h" #include "windows.h"
#include "ole2.h" #include "ole2.h"
#include "msxml2.h" #include "msxml2.h"
#include "msxml2did.h"
#include "ocidl.h" #include "ocidl.h"
#include "wine/test.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 */ /* Deprecated Error Code */
#define XML_E_INVALIDATROOTLEVEL 0xc00ce556 #define XML_E_INVALIDATROOTLEVEL 0xc00ce556
...@@ -49,25 +53,6 @@ static void create_xml_file(LPCSTR filename) ...@@ -49,25 +53,6 @@ static void create_xml_file(LPCSTR filename)
CloseHandle(hf); 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) static void create_stream_on_file(IStream **stream, LPCSTR path)
{ {
HANDLE hfile; HANDLE hfile;
...@@ -97,16 +82,18 @@ static void create_stream_on_file(IStream **stream, LPCSTR path) ...@@ -97,16 +82,18 @@ static void create_stream_on_file(IStream **stream, LPCSTR path)
static void test_xmldoc(void) static void test_xmldoc(void)
{ {
HRESULT hr;
IXMLDocument *doc = NULL;
IXMLElement *element = NULL, *child = NULL, *value = NULL; IXMLElement *element = NULL, *child = NULL, *value = NULL;
IXMLElementCollection *collection = NULL, *inner = NULL; IXMLElementCollection *collection = NULL, *inner = NULL;
IPersistStreamInit *psi = NULL; IPersistStreamInit *psi = NULL;
IXMLDocument *doc = NULL;
IStream *stream = NULL; IStream *stream = NULL;
CHAR path[MAX_PATH];
LONG type, num_child;
VARIANT vIndex, vName; 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 szBankAccount[] = {'B','A','N','K','A','C','C','O','U','N','T',0};
static const WCHAR szNumber[] = {'N','U','M','B','E','R',0}; static const WCHAR szNumber[] = {'N','U','M','B','E','R',0};
...@@ -114,16 +101,36 @@ static void test_xmldoc(void) ...@@ -114,16 +101,36 @@ static void test_xmldoc(void)
static const WCHAR szName[] = {'N','A','M','E',0}; 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 szNameVal[] = {'C','a','p','t','a','i','n',' ','A','h','a','b',0};
static const WCHAR szVersion[] = {'1','.','0',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, hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
&IID_IXMLDocument, (LPVOID*)&doc); &IID_IXMLDocument, (void**)&doc);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 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"); create_xml_file("bank.xml");
GetFullPathNameA("bank.xml", MAX_PATH, path, NULL); GetFullPathNameA("bank.xml", MAX_PATH, path, NULL);
create_stream_on_file(&stream, path); 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(hr == S_OK, "Expected S_OK, got %08x\n", hr);
ok(psi != NULL, "Expected non-NULL psi\n"); ok(psi != NULL, "Expected non-NULL psi\n");
...@@ -142,6 +149,7 @@ static void test_xmldoc(void) ...@@ -142,6 +149,7 @@ static void test_xmldoc(void)
hr = IXMLDocument_get_version(doc, NULL); hr = IXMLDocument_get_version(doc, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
name = NULL;
hr = IXMLDocument_get_version(doc, &name); hr = IXMLDocument_get_version(doc, &name);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 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)); ok(!lstrcmpW(name, szVersion), "Expected 1.0, got %s\n", wine_dbgstr_w(name));
......
...@@ -82,8 +82,8 @@ static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, vo ...@@ -82,8 +82,8 @@ static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, vo
TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
if (IsEqualGUID(riid, &IID_IUnknown) || if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IXMLDocument) || IsEqualGUID(riid, &IID_IDispatch) ||
IsEqualGUID(riid, &IID_IXMLDOMDocument)) IsEqualGUID(riid, &IID_IXMLDocument))
{ {
*ppvObject = iface; *ppvObject = iface;
} }
...@@ -107,18 +107,18 @@ static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, vo ...@@ -107,18 +107,18 @@ static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, vo
static ULONG WINAPI xmldoc_AddRef(IXMLDocument *iface) static ULONG WINAPI xmldoc_AddRef(IXMLDocument *iface)
{ {
xmldoc *This = impl_from_IXMLDocument(iface); xmldoc *This = impl_from_IXMLDocument(iface);
TRACE("%p\n", This); ULONG ref = InterlockedIncrement(&This->ref);
return InterlockedIncrement(&This->ref); TRACE("(%p)->(%d)\n", This, ref);
return ref;
} }
static ULONG WINAPI xmldoc_Release(IXMLDocument *iface) static ULONG WINAPI xmldoc_Release(IXMLDocument *iface)
{ {
xmldoc *This = impl_from_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) if (ref == 0)
{ {
xmlFreeDoc(This->xmldoc); xmlFreeDoc(This->xmldoc);
...@@ -144,13 +144,10 @@ static HRESULT WINAPI xmldoc_GetTypeInfo(IXMLDocument *iface, UINT iTInfo, ...@@ -144,13 +144,10 @@ static HRESULT WINAPI xmldoc_GetTypeInfo(IXMLDocument *iface, UINT iTInfo,
LCID lcid, ITypeInfo** ppTInfo) LCID lcid, ITypeInfo** ppTInfo)
{ {
xmldoc *This = impl_from_IXMLDocument(iface); xmldoc *This = impl_from_IXMLDocument(iface);
HRESULT hr;
TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
hr = get_typeinfo(IXMLDocument_tid, ppTInfo); return get_typeinfo(IXMLDocument_tid, ppTInfo);
return hr;
} }
static HRESULT WINAPI xmldoc_GetIDsOfNames(IXMLDocument *iface, REFIID riid, static HRESULT WINAPI xmldoc_GetIDsOfNames(IXMLDocument *iface, REFIID riid,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment