/* * 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 ); }