xref: /reactos/dll/win32/msxml3/factory.c (revision c7bba39a)
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