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