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 @@
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;
......
......@@ -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));
......
......@@ -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,
......
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