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