msxml3: Fix IDispatch support for IXMLDocument.
This commit is contained in:
parent
08a4ca7b53
commit
c32db17417
@ -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 {
|
|||||||
#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)
|
|||||||
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
|
|||||||
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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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
|
|||||||
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
|
|||||||
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,
|
|||||||
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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user