mshtml: Implement IHTMLDOMNode replaceChild.
[wine] / dlls / 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 #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)(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,  MSXML_DEFAULT },
63     { &CLSID_DOMDocument26, MSXML_DEFAULT },
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, MSXML_DEFAULT },
71     { &CLSID_FreeThreadedDOMDocument30, MSXML3 },
72     { &CLSID_FreeThreadedDOMDocument40, MSXML4 },
73     { &CLSID_FreeThreadedDOMDocument60, MSXML6 },
74
75     { &CLSID_XMLSchemaCache,   MSXML_DEFAULT },
76     { &CLSID_XMLSchemaCache26, MSXML_DEFAULT },
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
87 static MSXML_VERSION get_msxml_version(const GUID *clsid)
88 {
89     int i;
90
91     for (i = 0; i < sizeof(clsid_versions_table)/sizeof(struct clsid_version_t); i++)
92         if (IsEqualGUID(clsid, clsid_versions_table[i].clsid))
93             return clsid_versions_table[i].version;
94
95     ERR("unknown clsid=%s\n", debugstr_guid(clsid));
96     return MSXML_DEFAULT;
97 }
98
99 /******************************************************************************
100  * MSXML ClassFactory
101  */
102 typedef struct
103 {
104     IClassFactory IClassFactory_iface;
105     ClassFactoryCreateInstanceFunc pCreateInstance;
106 } ClassFactory;
107
108 typedef struct
109 {
110     IClassFactory IClassFactory_iface;
111     LONG ref;
112     DOMFactoryCreateInstanceFunc pCreateInstance;
113     MSXML_VERSION version;
114 } DOMFactory;
115
116 static inline ClassFactory *ClassFactory_from_IClassFactory(IClassFactory *iface)
117 {
118     return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
119 }
120
121 static HRESULT WINAPI ClassFactory_QueryInterface(
122     IClassFactory *iface,
123     REFIID riid,
124     void **ppobj )
125 {
126     if (IsEqualGUID(riid, &IID_IUnknown) ||
127         IsEqualGUID(riid, &IID_IClassFactory))
128     {
129         IClassFactory_AddRef( iface );
130         *ppobj = iface;
131         return S_OK;
132     }
133
134     FIXME("interface %s not implemented\n", debugstr_guid(riid));
135     *ppobj = NULL;
136     return E_NOINTERFACE;
137 }
138
139 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface )
140 {
141     return 2;
142 }
143
144 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface )
145 {
146     return 1;
147 }
148
149 static HRESULT WINAPI ClassFactory_CreateInstance(
150     IClassFactory *iface,
151     IUnknown *pOuter,
152     REFIID riid,
153     void **ppobj )
154 {
155     ClassFactory *This = ClassFactory_from_IClassFactory(iface);
156     IUnknown *punk;
157     HRESULT r;
158
159     TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
160
161     *ppobj = NULL;
162
163     if (pOuter)
164         return CLASS_E_NOAGGREGATION;
165
166     r = This->pCreateInstance( pOuter, (void**) &punk );
167     if (FAILED(r))
168         return r;
169
170     r = IUnknown_QueryInterface( punk, riid, ppobj );
171     IUnknown_Release( punk );
172     return r;
173 }
174
175 static HRESULT WINAPI ClassFactory_LockServer(
176     IClassFactory *iface,
177     BOOL dolock)
178 {
179     FIXME("(%p)->(%d),stub!\n",iface,dolock);
180     return S_OK;
181 }
182
183 static inline DOMFactory *DOMFactory_from_IClassFactory(IClassFactory *iface)
184 {
185     return CONTAINING_RECORD(iface, DOMFactory, IClassFactory_iface);
186 }
187
188 static ULONG WINAPI DOMClassFactory_AddRef(IClassFactory *iface )
189 {
190     DOMFactory *This = DOMFactory_from_IClassFactory(iface);
191     ULONG ref = InterlockedIncrement(&This->ref);
192     TRACE("(%p) ref = %u\n", This, ref);
193     return ref;
194 }
195
196 static ULONG WINAPI DOMClassFactory_Release(IClassFactory *iface )
197 {
198     DOMFactory *This = DOMFactory_from_IClassFactory(iface);
199     ULONG ref = InterlockedDecrement(&This->ref);
200     TRACE("(%p) ref = %u\n", This, ref);
201     if(!ref) {
202         heap_free(This);
203     }
204     return ref;
205 }
206
207 static HRESULT WINAPI DOMClassFactory_CreateInstance(
208     IClassFactory *iface,
209     IUnknown *pOuter,
210     REFIID riid,
211     void **ppobj )
212 {
213     DOMFactory *This = DOMFactory_from_IClassFactory(iface);
214     IUnknown *punk;
215     HRESULT r;
216
217     TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
218
219     *ppobj = NULL;
220
221     if (pOuter)
222         return CLASS_E_NOAGGREGATION;
223
224     r = This->pCreateInstance( This->version, pOuter, (void**) &punk );
225     if (FAILED(r))
226         return r;
227
228     r = IUnknown_QueryInterface( punk, riid, ppobj );
229     IUnknown_Release( punk );
230     return r;
231 }
232
233 static const struct IClassFactoryVtbl ClassFactoryVtbl =
234 {
235     ClassFactory_QueryInterface,
236     ClassFactory_AddRef,
237     ClassFactory_Release,
238     ClassFactory_CreateInstance,
239     ClassFactory_LockServer
240 };
241
242 static const struct IClassFactoryVtbl DOMClassFactoryVtbl =
243 {
244     ClassFactory_QueryInterface,
245     DOMClassFactory_AddRef,
246     DOMClassFactory_Release,
247     DOMClassFactory_CreateInstance,
248     ClassFactory_LockServer
249 };
250
251 static HRESULT DOMClassFactory_Create(const GUID *clsid, REFIID riid, void **ppv, DOMFactoryCreateInstanceFunc fnCreateInstance)
252 {
253     DOMFactory *ret = heap_alloc(sizeof(DOMFactory));
254     HRESULT hres;
255
256     ret->IClassFactory_iface.lpVtbl = &DOMClassFactoryVtbl;
257     ret->ref = 0;
258     ret->version = get_msxml_version(clsid);
259     ret->pCreateInstance = fnCreateInstance;
260
261     hres = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv);
262     if(FAILED(hres)) {
263         heap_free(ret);
264         *ppv = NULL;
265     }
266     return hres;
267 }
268
269 static ClassFactory xmldoccf = { { &ClassFactoryVtbl }, XMLDocument_create };
270 static ClassFactory saxreadcf = { { &ClassFactoryVtbl }, SAXXMLReader_create };
271 static ClassFactory httpreqcf = { { &ClassFactoryVtbl }, XMLHTTPRequest_create };
272 static ClassFactory xsltemplatecf = { { &ClassFactoryVtbl }, XSLTemplate_create };
273 static ClassFactory mxnsmanagercf = { {&ClassFactoryVtbl }, MXNamespaceManager_create };
274 static ClassFactory xmlparsercf = { { &ClassFactoryVtbl }, XMLParser_create };
275
276 /******************************************************************
277  *              DllGetClassObject (MSXML3.@)
278  */
279 HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
280 {
281     IClassFactory *cf = NULL;
282
283     TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv );
284
285     if( IsEqualCLSID( rclsid, &CLSID_DOMDocument )  ||  /* Version indep. v 2.x */
286         IsEqualCLSID( rclsid, &CLSID_DOMDocument2 ) ||  /* Version indep. v 3.0 */
287         IsEqualCLSID( rclsid, &CLSID_DOMDocument26 )||  /* Version dep.   v 2.6 */
288         IsEqualCLSID( rclsid, &CLSID_DOMDocument30 )||  /* Version dep.   v 3.0 */
289         IsEqualCLSID( rclsid, &CLSID_DOMDocument40 )||  /* Version dep.   v 4.0 */
290         IsEqualCLSID( rclsid, &CLSID_DOMDocument60 ))   /* Version dep.   v 6.0 */
291     {
292         return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
293     }
294     else if( IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache )   ||
295              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache26 ) ||
296              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache30 ) ||
297              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache40 ) ||
298              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache60 ))
299     {
300         return DOMClassFactory_Create(rclsid, riid, ppv, SchemaCache_create);
301     }
302     else if( IsEqualCLSID( rclsid, &CLSID_XMLDocument ) )
303     {
304         cf = &xmldoccf.IClassFactory_iface;
305     }
306     else if( IsEqualCLSID( rclsid, &CLSID_DOMFreeThreadedDocument )   ||   /* Version indep. v 2.x */
307              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument )   ||
308              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument26 ) ||
309              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument30 ) ||
310              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument40 ) ||
311              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument60 ))
312     {
313         return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
314     }
315     else if( IsEqualCLSID( rclsid, &CLSID_SAXXMLReader) ||
316              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader30 ) ||
317              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader40 ) ||
318              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader60 ))
319     {
320         cf = &saxreadcf.IClassFactory_iface;
321     }
322     else if( IsEqualCLSID( rclsid, &CLSID_XMLHTTPRequest ) ||
323              IsEqualCLSID( rclsid, &CLSID_XMLHTTP) ||
324              IsEqualCLSID( rclsid, &CLSID_XMLHTTP26 ) ||
325              IsEqualCLSID( rclsid, &CLSID_XMLHTTP30 ) ||
326              IsEqualCLSID( rclsid, &CLSID_XMLHTTP40 ) ||
327              IsEqualCLSID( rclsid, &CLSID_XMLHTTP60 ))
328     {
329         cf = &httpreqcf.IClassFactory_iface;
330     }
331     else if( IsEqualCLSID( rclsid, &CLSID_XSLTemplate )   ||
332              IsEqualCLSID( rclsid, &CLSID_XSLTemplate26 ) ||
333              IsEqualCLSID( rclsid, &CLSID_XSLTemplate30 ) ||
334              IsEqualCLSID( rclsid, &CLSID_XSLTemplate40 ) ||
335              IsEqualCLSID( rclsid, &CLSID_XSLTemplate60 ))
336     {
337         cf = &xsltemplatecf.IClassFactory_iface;
338     }
339     else if( IsEqualCLSID( rclsid, &CLSID_MXXMLWriter )   ||
340              IsEqualCLSID( rclsid, &CLSID_MXXMLWriter30 ) ||
341              IsEqualCLSID( rclsid, &CLSID_MXXMLWriter40 ) ||
342              IsEqualCLSID( rclsid, &CLSID_MXXMLWriter60 ) )
343     {
344         return DOMClassFactory_Create(rclsid, riid, ppv, MXWriter_create);
345     }
346     else if( IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager ) ||
347              IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager40 ) ||
348              IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager60 ) )
349     {
350         cf = &mxnsmanagercf.IClassFactory_iface;
351     }
352     else if( IsEqualCLSID( rclsid, &CLSID_XMLParser )  ||
353              IsEqualCLSID( rclsid, &CLSID_XMLParser26 ) ||
354              IsEqualCLSID( rclsid, &CLSID_XMLParser30 )  )
355     {
356         cf = &xmlparsercf.IClassFactory_iface;
357     }
358
359     if ( !cf )
360         return CLASS_E_CLASSNOTAVAILABLE;
361
362     return IClassFactory_QueryInterface( cf, riid, ppv );
363 }