395 lines
12 KiB
C
395 lines
12 KiB
C
/*
|
|
* MSXML Class Factory
|
|
*
|
|
* Copyright 2002 Lionel Ulmer
|
|
* Copyright 2005 Mike McCormack
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#define COBJMACROS
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdarg.h>
|
|
#ifdef HAVE_LIBXML2
|
|
# include <libxml/parser.h>
|
|
# include <libxml/xmlerror.h>
|
|
#endif
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "winuser.h"
|
|
#include "ole2.h"
|
|
#include "msxml.h"
|
|
#include "msxml2.h"
|
|
#include "xmlparser.h"
|
|
|
|
/* undef the #define in msxml2 so that we can access the v.2 version
|
|
independent CLSID as well as the v.3 one. */
|
|
#undef CLSID_DOMDocument
|
|
|
|
#include "wine/debug.h"
|
|
|
|
#include "msxml_private.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(msxml);
|
|
|
|
typedef HRESULT (*ClassFactoryCreateInstanceFunc)(void**);
|
|
typedef HRESULT (*DOMFactoryCreateInstanceFunc)(MSXML_VERSION, void**);
|
|
|
|
struct clsid_version_t
|
|
{
|
|
const GUID *clsid;
|
|
MSXML_VERSION version;
|
|
};
|
|
|
|
static const struct clsid_version_t clsid_versions_table[] =
|
|
{
|
|
{ &CLSID_DOMDocument, MSXML_DEFAULT },
|
|
{ &CLSID_DOMDocument2, MSXML2 },
|
|
{ &CLSID_DOMDocument26, MSXML26 },
|
|
{ &CLSID_DOMDocument30, MSXML3 },
|
|
{ &CLSID_DOMDocument40, MSXML4 },
|
|
{ &CLSID_DOMDocument60, MSXML6 },
|
|
|
|
{ &CLSID_DOMFreeThreadedDocument, MSXML_DEFAULT },
|
|
{ &CLSID_FreeThreadedDOMDocument, MSXML_DEFAULT },
|
|
{ &CLSID_FreeThreadedDOMDocument26, MSXML26 },
|
|
{ &CLSID_FreeThreadedDOMDocument30, MSXML3 },
|
|
{ &CLSID_FreeThreadedDOMDocument40, MSXML4 },
|
|
{ &CLSID_FreeThreadedDOMDocument60, MSXML6 },
|
|
|
|
{ &CLSID_XMLSchemaCache, MSXML_DEFAULT },
|
|
{ &CLSID_XMLSchemaCache26, MSXML26 },
|
|
{ &CLSID_XMLSchemaCache30, MSXML3 },
|
|
{ &CLSID_XMLSchemaCache40, MSXML4 },
|
|
{ &CLSID_XMLSchemaCache60, MSXML6 },
|
|
|
|
{ &CLSID_MXXMLWriter, MSXML_DEFAULT },
|
|
{ &CLSID_MXXMLWriter30, MSXML3 },
|
|
{ &CLSID_MXXMLWriter40, MSXML4 },
|
|
{ &CLSID_MXXMLWriter60, MSXML6 },
|
|
|
|
{ &CLSID_SAXXMLReader, MSXML_DEFAULT },
|
|
{ &CLSID_SAXXMLReader30, MSXML3 },
|
|
{ &CLSID_SAXXMLReader40, MSXML4 },
|
|
{ &CLSID_SAXXMLReader60, MSXML6 },
|
|
|
|
{ &CLSID_SAXAttributes, MSXML_DEFAULT },
|
|
{ &CLSID_SAXAttributes30, MSXML3 },
|
|
{ &CLSID_SAXAttributes40, MSXML4 },
|
|
{ &CLSID_SAXAttributes60, MSXML6 },
|
|
|
|
{ &CLSID_XMLView, MSXML_DEFAULT }
|
|
};
|
|
|
|
static MSXML_VERSION get_msxml_version(const GUID *clsid)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(clsid_versions_table); i++)
|
|
if (IsEqualGUID(clsid, clsid_versions_table[i].clsid))
|
|
return clsid_versions_table[i].version;
|
|
|
|
ERR("unknown clsid=%s\n", debugstr_guid(clsid));
|
|
return MSXML_DEFAULT;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* MSXML ClassFactory
|
|
*/
|
|
typedef struct
|
|
{
|
|
IClassFactory IClassFactory_iface;
|
|
ClassFactoryCreateInstanceFunc pCreateInstance;
|
|
} ClassFactory;
|
|
|
|
typedef struct
|
|
{
|
|
IClassFactory IClassFactory_iface;
|
|
LONG ref;
|
|
DOMFactoryCreateInstanceFunc pCreateInstance;
|
|
MSXML_VERSION version;
|
|
} DOMFactory;
|
|
|
|
static inline ClassFactory *ClassFactory_from_IClassFactory(IClassFactory *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI ClassFactory_QueryInterface(
|
|
IClassFactory *iface,
|
|
REFIID riid,
|
|
void **ppobj )
|
|
{
|
|
if (IsEqualGUID(riid, &IID_IUnknown) ||
|
|
IsEqualGUID(riid, &IID_IClassFactory))
|
|
{
|
|
IClassFactory_AddRef( iface );
|
|
*ppobj = iface;
|
|
return S_OK;
|
|
}
|
|
|
|
FIXME("interface %s not implemented\n", debugstr_guid(riid));
|
|
*ppobj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface )
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
static ULONG WINAPI ClassFactory_Release(IClassFactory *iface )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static HRESULT WINAPI ClassFactory_CreateInstance(
|
|
IClassFactory *iface,
|
|
IUnknown *pOuter,
|
|
REFIID riid,
|
|
void **ppobj )
|
|
{
|
|
ClassFactory *This = ClassFactory_from_IClassFactory(iface);
|
|
IUnknown *punk;
|
|
HRESULT r;
|
|
|
|
TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
|
|
|
|
*ppobj = NULL;
|
|
|
|
if (pOuter)
|
|
return CLASS_E_NOAGGREGATION;
|
|
|
|
r = This->pCreateInstance( (void**) &punk );
|
|
if (FAILED(r))
|
|
return r;
|
|
|
|
r = IUnknown_QueryInterface( punk, riid, ppobj );
|
|
IUnknown_Release( punk );
|
|
return r;
|
|
}
|
|
|
|
static HRESULT WINAPI ClassFactory_LockServer(
|
|
IClassFactory *iface,
|
|
BOOL dolock)
|
|
{
|
|
FIXME("(%p)->(%d),stub!\n",iface,dolock);
|
|
return S_OK;
|
|
}
|
|
|
|
static inline DOMFactory *DOMFactory_from_IClassFactory(IClassFactory *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, DOMFactory, IClassFactory_iface);
|
|
}
|
|
|
|
static ULONG WINAPI DOMClassFactory_AddRef(IClassFactory *iface )
|
|
{
|
|
DOMFactory *This = DOMFactory_from_IClassFactory(iface);
|
|
ULONG ref = InterlockedIncrement(&This->ref);
|
|
TRACE("(%p) ref = %u\n", This, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI DOMClassFactory_Release(IClassFactory *iface )
|
|
{
|
|
DOMFactory *This = DOMFactory_from_IClassFactory(iface);
|
|
ULONG ref = InterlockedDecrement(&This->ref);
|
|
TRACE("(%p) ref = %u\n", This, ref);
|
|
if(!ref) {
|
|
heap_free(This);
|
|
}
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI DOMClassFactory_CreateInstance(
|
|
IClassFactory *iface,
|
|
IUnknown *pOuter,
|
|
REFIID riid,
|
|
void **ppobj )
|
|
{
|
|
DOMFactory *This = DOMFactory_from_IClassFactory(iface);
|
|
IUnknown *punk;
|
|
HRESULT r;
|
|
|
|
TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
|
|
|
|
*ppobj = NULL;
|
|
|
|
if (pOuter)
|
|
return CLASS_E_NOAGGREGATION;
|
|
|
|
r = This->pCreateInstance( This->version, (void**) &punk );
|
|
if (FAILED(r))
|
|
return r;
|
|
|
|
r = IUnknown_QueryInterface( punk, riid, ppobj );
|
|
IUnknown_Release( punk );
|
|
return r;
|
|
}
|
|
|
|
static const struct IClassFactoryVtbl ClassFactoryVtbl =
|
|
{
|
|
ClassFactory_QueryInterface,
|
|
ClassFactory_AddRef,
|
|
ClassFactory_Release,
|
|
ClassFactory_CreateInstance,
|
|
ClassFactory_LockServer
|
|
};
|
|
|
|
static const struct IClassFactoryVtbl DOMClassFactoryVtbl =
|
|
{
|
|
ClassFactory_QueryInterface,
|
|
DOMClassFactory_AddRef,
|
|
DOMClassFactory_Release,
|
|
DOMClassFactory_CreateInstance,
|
|
ClassFactory_LockServer
|
|
};
|
|
|
|
static HRESULT DOMClassFactory_Create(const GUID *clsid, REFIID riid, void **ppv, DOMFactoryCreateInstanceFunc fnCreateInstance)
|
|
{
|
|
DOMFactory *ret = heap_alloc(sizeof(DOMFactory));
|
|
HRESULT hres;
|
|
|
|
ret->IClassFactory_iface.lpVtbl = &DOMClassFactoryVtbl;
|
|
ret->ref = 0;
|
|
ret->version = get_msxml_version(clsid);
|
|
ret->pCreateInstance = fnCreateInstance;
|
|
|
|
hres = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv);
|
|
if(FAILED(hres)) {
|
|
heap_free(ret);
|
|
*ppv = NULL;
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
static ClassFactory xmldoccf = { { &ClassFactoryVtbl }, XMLDocument_create };
|
|
static ClassFactory httpreqcf = { { &ClassFactoryVtbl }, XMLHTTPRequest_create };
|
|
static ClassFactory serverhttp = { { &ClassFactoryVtbl }, ServerXMLHTTP_create };
|
|
static ClassFactory xsltemplatecf = { { &ClassFactoryVtbl }, XSLTemplate_create };
|
|
static ClassFactory mxnsmanagercf = { {&ClassFactoryVtbl }, MXNamespaceManager_create };
|
|
static ClassFactory xmlparsercf = { { &ClassFactoryVtbl }, XMLParser_create };
|
|
static ClassFactory xmlviewcf = { { &ClassFactoryVtbl }, XMLView_create };
|
|
|
|
/******************************************************************
|
|
* DllGetClassObject (MSXML3.@)
|
|
*/
|
|
HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
|
|
{
|
|
IClassFactory *cf = NULL;
|
|
|
|
TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv );
|
|
|
|
if( IsEqualCLSID( rclsid, &CLSID_DOMDocument ) || /* Version indep. v 2.x */
|
|
IsEqualCLSID( rclsid, &CLSID_DOMDocument2 ) || /* Version indep. v 3.0 */
|
|
IsEqualCLSID( rclsid, &CLSID_DOMDocument26 )|| /* Version dep. v 2.6 */
|
|
IsEqualCLSID( rclsid, &CLSID_DOMDocument30 )|| /* Version dep. v 3.0 */
|
|
IsEqualCLSID( rclsid, &CLSID_DOMDocument40 )|| /* Version dep. v 4.0 */
|
|
IsEqualCLSID( rclsid, &CLSID_DOMDocument60 )) /* Version dep. v 6.0 */
|
|
{
|
|
return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache26 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache30 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache40 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache60 ))
|
|
{
|
|
return DOMClassFactory_Create(rclsid, riid, ppv, SchemaCache_create);
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_XMLDocument ) )
|
|
{
|
|
cf = &xmldoccf.IClassFactory_iface;
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_DOMFreeThreadedDocument ) || /* Version indep. v 2.x */
|
|
IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument26 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument30 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument40 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument60 ))
|
|
{
|
|
return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_SAXXMLReader) ||
|
|
IsEqualCLSID( rclsid, &CLSID_SAXXMLReader30 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_SAXXMLReader40 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_SAXXMLReader60 ))
|
|
{
|
|
return DOMClassFactory_Create(rclsid, riid, ppv, SAXXMLReader_create);
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_XMLHTTPRequest ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLHTTP) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLHTTP26 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLHTTP30 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLHTTP40 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLHTTP60 ))
|
|
{
|
|
cf = &httpreqcf.IClassFactory_iface;
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP30 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP40 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP60 ))
|
|
{
|
|
cf = &serverhttp.IClassFactory_iface;
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_XSLTemplate ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XSLTemplate26 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XSLTemplate30 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XSLTemplate40 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XSLTemplate60 ))
|
|
{
|
|
cf = &xsltemplatecf.IClassFactory_iface;
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_MXXMLWriter ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_MXXMLWriter30 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_MXXMLWriter40 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_MXXMLWriter60 ) )
|
|
{
|
|
return DOMClassFactory_Create(rclsid, riid, ppv, MXWriter_create);
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_SAXAttributes) ||
|
|
IsEqualCLSID( rclsid, &CLSID_SAXAttributes30 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_SAXAttributes40 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_SAXAttributes60 ))
|
|
{
|
|
return DOMClassFactory_Create(rclsid, riid, ppv, SAXAttributes_create);
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager40 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager60 ) )
|
|
{
|
|
cf = &mxnsmanagercf.IClassFactory_iface;
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_XMLParser ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLParser26 ) ||
|
|
IsEqualCLSID( rclsid, &CLSID_XMLParser30 ) )
|
|
{
|
|
cf = &xmlparsercf.IClassFactory_iface;
|
|
}
|
|
else if( IsEqualCLSID( rclsid, &CLSID_XMLView ) )
|
|
{
|
|
cf = &xmlviewcf.IClassFactory_iface;
|
|
}
|
|
|
|
if ( !cf )
|
|
return CLASS_E_CLASSNOTAVAILABLE;
|
|
|
|
return IClassFactory_QueryInterface( cf, riid, ppv );
|
|
}
|