cb9ac32d3ca0d2e076203533a1682adc9104cd63
[reactos.git] / reactos / dll / win32 / msxml3 / factory.c
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 #include <config.h>
23
24 #ifdef HAVE_LIBXML2
25 # include <libxml/parser.h>
26 #endif
27
28 #define WIN32_NO_STATUS
29 #define _INC_WINDOWS
30
31 #define COBJMACROS
32
33 #include <windef.h>
34 #include <winbase.h>
35 #include <ole2.h>
36 #include <msxml2.h>
37
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)(IUnknown*, void**);
51 typedef HRESULT (*DOMFactoryCreateInstanceFunc)(MSXML_VERSION, IUnknown*, 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 < sizeof(clsid_versions_table)/sizeof(struct clsid_version_t); 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( pOuter, (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, pOuter, (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 }