wine/dlls/msxml3/factory.c

368 lines
11 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)(IUnknown*, void**);
typedef HRESULT (*DOMFactoryCreateInstanceFunc)(MSXML_VERSION, IUnknown*, 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, MSXML_DEFAULT },
{ &CLSID_DOMDocument26, MSXML_DEFAULT },
{ &CLSID_DOMDocument30, MSXML3 },
{ &CLSID_DOMDocument40, MSXML4 },
{ &CLSID_DOMDocument60, MSXML6 },
{ &CLSID_DOMFreeThreadedDocument, MSXML_DEFAULT },
{ &CLSID_FreeThreadedDOMDocument, MSXML_DEFAULT },
{ &CLSID_FreeThreadedDOMDocument26, MSXML_DEFAULT },
{ &CLSID_FreeThreadedDOMDocument30, MSXML3 },
{ &CLSID_FreeThreadedDOMDocument40, MSXML4 },
{ &CLSID_FreeThreadedDOMDocument60, MSXML6 },
{ &CLSID_XMLSchemaCache, MSXML_DEFAULT },
{ &CLSID_XMLSchemaCache26, MSXML_DEFAULT },
{ &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 }
};
static MSXML_VERSION get_msxml_version(const GUID *clsid)
{
int i;
for (i = 0; i < sizeof(clsid_versions_table)/sizeof(struct clsid_version_t); 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( pOuter, (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, pOuter, (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 xsltemplatecf = { { &ClassFactoryVtbl }, XSLTemplate_create };
static ClassFactory mxnsmanagercf = { {&ClassFactoryVtbl }, MXNamespaceManager_create };
static ClassFactory xmlparsercf = { { &ClassFactoryVtbl }, XMLParser_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_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_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;
}
if ( !cf )
return CLASS_E_CLASSNOTAVAILABLE;
return IClassFactory_QueryInterface( cf, riid, ppv );
}