1 /* 2 * MSXML Class Factory 3 * 4 * Copyright 2002 Lionel Ulmer 5 * Copyright 2005 Mike McCormack 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define COBJMACROS 23 24 #include "config.h" 25 26 #include <stdarg.h> 27 #ifdef HAVE_LIBXML2 28 # include <libxml/parser.h> 29 # include <libxml/xmlerror.h> 30 #endif 31 32 #include "windef.h" 33 #include "winbase.h" 34 #include "winuser.h" 35 #include "ole2.h" 36 #include "msxml.h" 37 #include "msxml2.h" 38 #include "xmlparser.h" 39 40 /* undef the #define in msxml2 so that we can access the v.2 version 41 independent CLSID as well as the v.3 one. */ 42 #undef CLSID_DOMDocument 43 44 #include "wine/debug.h" 45 46 #include "msxml_private.h" 47 48 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 49 50 typedef HRESULT (*ClassFactoryCreateInstanceFunc)(void**); 51 typedef HRESULT (*DOMFactoryCreateInstanceFunc)(MSXML_VERSION, void**); 52 53 struct clsid_version_t 54 { 55 const GUID *clsid; 56 MSXML_VERSION version; 57 }; 58 59 static const struct clsid_version_t clsid_versions_table[] = 60 { 61 { &CLSID_DOMDocument, MSXML_DEFAULT }, 62 { &CLSID_DOMDocument2, MSXML2 }, 63 { &CLSID_DOMDocument26, MSXML26 }, 64 { &CLSID_DOMDocument30, MSXML3 }, 65 { &CLSID_DOMDocument40, MSXML4 }, 66 { &CLSID_DOMDocument60, MSXML6 }, 67 68 { &CLSID_DOMFreeThreadedDocument, MSXML_DEFAULT }, 69 { &CLSID_FreeThreadedDOMDocument, MSXML_DEFAULT }, 70 { &CLSID_FreeThreadedDOMDocument26, MSXML26 }, 71 { &CLSID_FreeThreadedDOMDocument30, MSXML3 }, 72 { &CLSID_FreeThreadedDOMDocument40, MSXML4 }, 73 { &CLSID_FreeThreadedDOMDocument60, MSXML6 }, 74 75 { &CLSID_XMLSchemaCache, MSXML_DEFAULT }, 76 { &CLSID_XMLSchemaCache26, MSXML26 }, 77 { &CLSID_XMLSchemaCache30, MSXML3 }, 78 { &CLSID_XMLSchemaCache40, MSXML4 }, 79 { &CLSID_XMLSchemaCache60, MSXML6 }, 80 81 { &CLSID_MXXMLWriter, MSXML_DEFAULT }, 82 { &CLSID_MXXMLWriter30, MSXML3 }, 83 { &CLSID_MXXMLWriter40, MSXML4 }, 84 { &CLSID_MXXMLWriter60, MSXML6 }, 85 86 { &CLSID_SAXXMLReader, MSXML_DEFAULT }, 87 { &CLSID_SAXXMLReader30, MSXML3 }, 88 { &CLSID_SAXXMLReader40, MSXML4 }, 89 { &CLSID_SAXXMLReader60, MSXML6 }, 90 91 { &CLSID_SAXAttributes, MSXML_DEFAULT }, 92 { &CLSID_SAXAttributes30, MSXML3 }, 93 { &CLSID_SAXAttributes40, MSXML4 }, 94 { &CLSID_SAXAttributes60, MSXML6 }, 95 96 { &CLSID_XMLView, MSXML_DEFAULT } 97 }; 98 99 static MSXML_VERSION get_msxml_version(const GUID *clsid) 100 { 101 unsigned int i; 102 103 for (i = 0; i < ARRAY_SIZE(clsid_versions_table); i++) 104 if (IsEqualGUID(clsid, clsid_versions_table[i].clsid)) 105 return clsid_versions_table[i].version; 106 107 ERR("unknown clsid=%s\n", debugstr_guid(clsid)); 108 return MSXML_DEFAULT; 109 } 110 111 /****************************************************************************** 112 * MSXML ClassFactory 113 */ 114 typedef struct 115 { 116 IClassFactory IClassFactory_iface; 117 ClassFactoryCreateInstanceFunc pCreateInstance; 118 } ClassFactory; 119 120 typedef struct 121 { 122 IClassFactory IClassFactory_iface; 123 LONG ref; 124 DOMFactoryCreateInstanceFunc pCreateInstance; 125 MSXML_VERSION version; 126 } DOMFactory; 127 128 static inline ClassFactory *ClassFactory_from_IClassFactory(IClassFactory *iface) 129 { 130 return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface); 131 } 132 133 static HRESULT WINAPI ClassFactory_QueryInterface( 134 IClassFactory *iface, 135 REFIID riid, 136 void **ppobj ) 137 { 138 if (IsEqualGUID(riid, &IID_IUnknown) || 139 IsEqualGUID(riid, &IID_IClassFactory)) 140 { 141 IClassFactory_AddRef( iface ); 142 *ppobj = iface; 143 return S_OK; 144 } 145 146 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 147 *ppobj = NULL; 148 return E_NOINTERFACE; 149 } 150 151 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface ) 152 { 153 return 2; 154 } 155 156 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface ) 157 { 158 return 1; 159 } 160 161 static HRESULT WINAPI ClassFactory_CreateInstance( 162 IClassFactory *iface, 163 IUnknown *pOuter, 164 REFIID riid, 165 void **ppobj ) 166 { 167 ClassFactory *This = ClassFactory_from_IClassFactory(iface); 168 IUnknown *punk; 169 HRESULT r; 170 171 TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj ); 172 173 *ppobj = NULL; 174 175 if (pOuter) 176 return CLASS_E_NOAGGREGATION; 177 178 r = This->pCreateInstance( (void**) &punk ); 179 if (FAILED(r)) 180 return r; 181 182 r = IUnknown_QueryInterface( punk, riid, ppobj ); 183 IUnknown_Release( punk ); 184 return r; 185 } 186 187 static HRESULT WINAPI ClassFactory_LockServer( 188 IClassFactory *iface, 189 BOOL dolock) 190 { 191 FIXME("(%p)->(%d),stub!\n",iface,dolock); 192 return S_OK; 193 } 194 195 static inline DOMFactory *DOMFactory_from_IClassFactory(IClassFactory *iface) 196 { 197 return CONTAINING_RECORD(iface, DOMFactory, IClassFactory_iface); 198 } 199 200 static ULONG WINAPI DOMClassFactory_AddRef(IClassFactory *iface ) 201 { 202 DOMFactory *This = DOMFactory_from_IClassFactory(iface); 203 ULONG ref = InterlockedIncrement(&This->ref); 204 TRACE("(%p) ref = %u\n", This, ref); 205 return ref; 206 } 207 208 static ULONG WINAPI DOMClassFactory_Release(IClassFactory *iface ) 209 { 210 DOMFactory *This = DOMFactory_from_IClassFactory(iface); 211 ULONG ref = InterlockedDecrement(&This->ref); 212 TRACE("(%p) ref = %u\n", This, ref); 213 if(!ref) { 214 heap_free(This); 215 } 216 return ref; 217 } 218 219 static HRESULT WINAPI DOMClassFactory_CreateInstance( 220 IClassFactory *iface, 221 IUnknown *pOuter, 222 REFIID riid, 223 void **ppobj ) 224 { 225 DOMFactory *This = DOMFactory_from_IClassFactory(iface); 226 IUnknown *punk; 227 HRESULT r; 228 229 TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj ); 230 231 *ppobj = NULL; 232 233 if (pOuter) 234 return CLASS_E_NOAGGREGATION; 235 236 r = This->pCreateInstance( This->version, (void**) &punk ); 237 if (FAILED(r)) 238 return r; 239 240 r = IUnknown_QueryInterface( punk, riid, ppobj ); 241 IUnknown_Release( punk ); 242 return r; 243 } 244 245 static const struct IClassFactoryVtbl ClassFactoryVtbl = 246 { 247 ClassFactory_QueryInterface, 248 ClassFactory_AddRef, 249 ClassFactory_Release, 250 ClassFactory_CreateInstance, 251 ClassFactory_LockServer 252 }; 253 254 static const struct IClassFactoryVtbl DOMClassFactoryVtbl = 255 { 256 ClassFactory_QueryInterface, 257 DOMClassFactory_AddRef, 258 DOMClassFactory_Release, 259 DOMClassFactory_CreateInstance, 260 ClassFactory_LockServer 261 }; 262 263 static HRESULT DOMClassFactory_Create(const GUID *clsid, REFIID riid, void **ppv, DOMFactoryCreateInstanceFunc fnCreateInstance) 264 { 265 DOMFactory *ret = heap_alloc(sizeof(DOMFactory)); 266 HRESULT hres; 267 268 ret->IClassFactory_iface.lpVtbl = &DOMClassFactoryVtbl; 269 ret->ref = 0; 270 ret->version = get_msxml_version(clsid); 271 ret->pCreateInstance = fnCreateInstance; 272 273 hres = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv); 274 if(FAILED(hres)) { 275 heap_free(ret); 276 *ppv = NULL; 277 } 278 return hres; 279 } 280 281 static ClassFactory xmldoccf = { { &ClassFactoryVtbl }, XMLDocument_create }; 282 static ClassFactory httpreqcf = { { &ClassFactoryVtbl }, XMLHTTPRequest_create }; 283 static ClassFactory serverhttp = { { &ClassFactoryVtbl }, ServerXMLHTTP_create }; 284 static ClassFactory xsltemplatecf = { { &ClassFactoryVtbl }, XSLTemplate_create }; 285 static ClassFactory mxnsmanagercf = { {&ClassFactoryVtbl }, MXNamespaceManager_create }; 286 static ClassFactory xmlparsercf = { { &ClassFactoryVtbl }, XMLParser_create }; 287 static ClassFactory xmlviewcf = { { &ClassFactoryVtbl }, XMLView_create }; 288 289 /****************************************************************** 290 * DllGetClassObject (MSXML3.@) 291 */ 292 HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv ) 293 { 294 IClassFactory *cf = NULL; 295 296 TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv ); 297 298 if( IsEqualCLSID( rclsid, &CLSID_DOMDocument ) || /* Version indep. v 2.x */ 299 IsEqualCLSID( rclsid, &CLSID_DOMDocument2 ) || /* Version indep. v 3.0 */ 300 IsEqualCLSID( rclsid, &CLSID_DOMDocument26 )|| /* Version dep. v 2.6 */ 301 IsEqualCLSID( rclsid, &CLSID_DOMDocument30 )|| /* Version dep. v 3.0 */ 302 IsEqualCLSID( rclsid, &CLSID_DOMDocument40 )|| /* Version dep. v 4.0 */ 303 IsEqualCLSID( rclsid, &CLSID_DOMDocument60 )) /* Version dep. v 6.0 */ 304 { 305 return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create); 306 } 307 else if( IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache ) || 308 IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache26 ) || 309 IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache30 ) || 310 IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache40 ) || 311 IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache60 )) 312 { 313 return DOMClassFactory_Create(rclsid, riid, ppv, SchemaCache_create); 314 } 315 else if( IsEqualCLSID( rclsid, &CLSID_XMLDocument ) ) 316 { 317 cf = &xmldoccf.IClassFactory_iface; 318 } 319 else if( IsEqualCLSID( rclsid, &CLSID_DOMFreeThreadedDocument ) || /* Version indep. v 2.x */ 320 IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument ) || 321 IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument26 ) || 322 IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument30 ) || 323 IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument40 ) || 324 IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument60 )) 325 { 326 return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create); 327 } 328 else if( IsEqualCLSID( rclsid, &CLSID_SAXXMLReader) || 329 IsEqualCLSID( rclsid, &CLSID_SAXXMLReader30 ) || 330 IsEqualCLSID( rclsid, &CLSID_SAXXMLReader40 ) || 331 IsEqualCLSID( rclsid, &CLSID_SAXXMLReader60 )) 332 { 333 return DOMClassFactory_Create(rclsid, riid, ppv, SAXXMLReader_create); 334 } 335 else if( IsEqualCLSID( rclsid, &CLSID_XMLHTTPRequest ) || 336 IsEqualCLSID( rclsid, &CLSID_XMLHTTP) || 337 IsEqualCLSID( rclsid, &CLSID_XMLHTTP26 ) || 338 IsEqualCLSID( rclsid, &CLSID_XMLHTTP30 ) || 339 IsEqualCLSID( rclsid, &CLSID_XMLHTTP40 ) || 340 IsEqualCLSID( rclsid, &CLSID_XMLHTTP60 )) 341 { 342 cf = &httpreqcf.IClassFactory_iface; 343 } 344 else if( IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP ) || 345 IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP30 ) || 346 IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP40 ) || 347 IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP60 )) 348 { 349 cf = &serverhttp.IClassFactory_iface; 350 } 351 else if( IsEqualCLSID( rclsid, &CLSID_XSLTemplate ) || 352 IsEqualCLSID( rclsid, &CLSID_XSLTemplate26 ) || 353 IsEqualCLSID( rclsid, &CLSID_XSLTemplate30 ) || 354 IsEqualCLSID( rclsid, &CLSID_XSLTemplate40 ) || 355 IsEqualCLSID( rclsid, &CLSID_XSLTemplate60 )) 356 { 357 cf = &xsltemplatecf.IClassFactory_iface; 358 } 359 else if( IsEqualCLSID( rclsid, &CLSID_MXXMLWriter ) || 360 IsEqualCLSID( rclsid, &CLSID_MXXMLWriter30 ) || 361 IsEqualCLSID( rclsid, &CLSID_MXXMLWriter40 ) || 362 IsEqualCLSID( rclsid, &CLSID_MXXMLWriter60 ) ) 363 { 364 return DOMClassFactory_Create(rclsid, riid, ppv, MXWriter_create); 365 } 366 else if( IsEqualCLSID( rclsid, &CLSID_SAXAttributes) || 367 IsEqualCLSID( rclsid, &CLSID_SAXAttributes30 ) || 368 IsEqualCLSID( rclsid, &CLSID_SAXAttributes40 ) || 369 IsEqualCLSID( rclsid, &CLSID_SAXAttributes60 )) 370 { 371 return DOMClassFactory_Create(rclsid, riid, ppv, SAXAttributes_create); 372 } 373 else if( IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager ) || 374 IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager40 ) || 375 IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager60 ) ) 376 { 377 cf = &mxnsmanagercf.IClassFactory_iface; 378 } 379 else if( IsEqualCLSID( rclsid, &CLSID_XMLParser ) || 380 IsEqualCLSID( rclsid, &CLSID_XMLParser26 ) || 381 IsEqualCLSID( rclsid, &CLSID_XMLParser30 ) ) 382 { 383 cf = &xmlparsercf.IClassFactory_iface; 384 } 385 else if( IsEqualCLSID( rclsid, &CLSID_XMLView ) ) 386 { 387 cf = &xmlviewcf.IClassFactory_iface; 388 } 389 390 if ( !cf ) 391 return CLASS_E_CLASSNOTAVAILABLE; 392 393 return IClassFactory_QueryInterface( cf, riid, ppv ); 394 } 395