msxml3: Create CLSID_XMLHTTP when requested.
[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 *pUnkOuter, LPVOID *ppObj);
50 typedef HRESULT (*DOMFactoryCreateInstanceFunc)(const GUID *clsid, IUnknown *pUnkOuter, LPVOID *ppObj);
51
52 /******************************************************************************
53  * MSXML ClassFactory
54  */
55 typedef struct
56 {
57     IClassFactory IClassFactory_iface;
58     ClassFactoryCreateInstanceFunc pCreateInstance;
59 } ClassFactory;
60
61 typedef struct
62 {
63     IClassFactory IClassFactory_iface;
64     LONG ref;
65     DOMFactoryCreateInstanceFunc pCreateInstance;
66     GUID clsid;
67 } DOMFactory;
68
69 static inline ClassFactory *ClassFactory_from_IClassFactory(IClassFactory *iface)
70 {
71     return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
72 }
73
74 static HRESULT WINAPI ClassFactory_QueryInterface(
75     IClassFactory *iface,
76     REFIID riid,
77     void **ppobj )
78 {
79     if (IsEqualGUID(riid, &IID_IUnknown) ||
80         IsEqualGUID(riid, &IID_IClassFactory))
81     {
82         IClassFactory_AddRef( iface );
83         *ppobj = iface;
84         return S_OK;
85     }
86
87     FIXME("interface %s not implemented\n", debugstr_guid(riid));
88     *ppobj = NULL;
89     return E_NOINTERFACE;
90 }
91
92 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface )
93 {
94     return 2;
95 }
96
97 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface )
98 {
99     return 1;
100 }
101
102 static HRESULT WINAPI ClassFactory_CreateInstance(
103     IClassFactory *iface,
104     IUnknown *pOuter,
105     REFIID riid,
106     void **ppobj )
107 {
108     ClassFactory *This = ClassFactory_from_IClassFactory(iface);
109     IUnknown *punk;
110     HRESULT r;
111
112     TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
113
114     *ppobj = NULL;
115
116     if (pOuter)
117         return CLASS_E_NOAGGREGATION;
118
119     r = This->pCreateInstance( pOuter, (void**) &punk );
120     if (FAILED(r))
121         return r;
122
123     r = IUnknown_QueryInterface( punk, riid, ppobj );
124     IUnknown_Release( punk );
125     return r;
126 }
127
128 static HRESULT WINAPI ClassFactory_LockServer(
129     IClassFactory *iface,
130     BOOL dolock)
131 {
132     FIXME("(%p)->(%d),stub!\n",iface,dolock);
133     return S_OK;
134 }
135
136 static inline DOMFactory *DOMFactory_from_IClassFactory(IClassFactory *iface)
137 {
138     return CONTAINING_RECORD(iface, DOMFactory, IClassFactory_iface);
139 }
140
141 static ULONG WINAPI DOMClassFactory_AddRef(IClassFactory *iface )
142 {
143     DOMFactory *This = DOMFactory_from_IClassFactory(iface);
144     ULONG ref = InterlockedIncrement(&This->ref);
145     TRACE("(%p) ref = %u\n", This, ref);
146     return ref;
147 }
148
149 static ULONG WINAPI DOMClassFactory_Release(IClassFactory *iface )
150 {
151     DOMFactory *This = DOMFactory_from_IClassFactory(iface);
152     ULONG ref = InterlockedDecrement(&This->ref);
153     TRACE("(%p) ref = %u\n", This, ref);
154     if(!ref) {
155         heap_free(This);
156     }
157     return ref;
158 }
159
160 static HRESULT WINAPI DOMClassFactory_CreateInstance(
161     IClassFactory *iface,
162     IUnknown *pOuter,
163     REFIID riid,
164     void **ppobj )
165 {
166     DOMFactory *This = DOMFactory_from_IClassFactory(iface);
167     IUnknown *punk;
168     HRESULT r;
169
170     TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
171
172     *ppobj = NULL;
173
174     if (pOuter)
175         return CLASS_E_NOAGGREGATION;
176
177     r = This->pCreateInstance( &This->clsid, pOuter, (void**) &punk );
178     if (FAILED(r))
179         return r;
180
181     r = IUnknown_QueryInterface( punk, riid, ppobj );
182     IUnknown_Release( punk );
183     return r;
184 }
185
186 static const struct IClassFactoryVtbl ClassFactoryVtbl =
187 {
188     ClassFactory_QueryInterface,
189     ClassFactory_AddRef,
190     ClassFactory_Release,
191     ClassFactory_CreateInstance,
192     ClassFactory_LockServer
193 };
194
195 static const struct IClassFactoryVtbl DOMClassFactoryVtbl =
196 {
197     ClassFactory_QueryInterface,
198     DOMClassFactory_AddRef,
199     DOMClassFactory_Release,
200     DOMClassFactory_CreateInstance,
201     ClassFactory_LockServer
202 };
203
204 static HRESULT DOMClassFactory_Create(const GUID *clsid, REFIID riid, void **ppv, DOMFactoryCreateInstanceFunc fnCreateInstance)
205 {
206     DOMFactory *ret = heap_alloc(sizeof(DOMFactory));
207     HRESULT hres;
208
209     ret->IClassFactory_iface.lpVtbl = &DOMClassFactoryVtbl;
210     ret->ref = 0;
211     ret->clsid = *clsid;
212     ret->pCreateInstance = fnCreateInstance;
213
214     hres = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv);
215     if(FAILED(hres)) {
216         heap_free(ret);
217         *ppv = NULL;
218     }
219     return hres;
220 }
221
222 static ClassFactory xmldoccf = { { &ClassFactoryVtbl }, XMLDocument_create };
223 static ClassFactory saxreadcf = { { &ClassFactoryVtbl }, SAXXMLReader_create };
224 static ClassFactory httpreqcf = { { &ClassFactoryVtbl }, XMLHTTPRequest_create };
225 static ClassFactory xsltemplatecf = { { &ClassFactoryVtbl }, XSLTemplate_create };
226 static ClassFactory mxwritercf = { { &ClassFactoryVtbl }, MXWriter_create };
227
228 /******************************************************************
229  *              DllGetClassObject (MSXML3.@)
230  */
231 HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
232 {
233     IClassFactory *cf = NULL;
234
235     TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv );
236
237     if( IsEqualCLSID( rclsid, &CLSID_DOMDocument )  ||  /* Version indep. v 2.x */
238         IsEqualCLSID( rclsid, &CLSID_DOMDocument2 ) ||  /* Version indep. v 3.0 */
239         IsEqualCLSID( rclsid, &CLSID_DOMDocument26 )||  /* Version dep.   v 2.6 */
240         IsEqualCLSID( rclsid, &CLSID_DOMDocument30 )||  /* Version dep.   v 3.0 */
241         IsEqualCLSID( rclsid, &CLSID_DOMDocument40 )||  /* Version dep.   v 4.0 */
242         IsEqualCLSID( rclsid, &CLSID_DOMDocument60 ))   /* Version dep.   v 6.0 */
243     {
244         return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
245     }
246     else if( IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache )   ||
247              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache26 ) ||
248              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache30 ) ||
249              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache40 ) ||
250              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache60 ))
251     {
252         return DOMClassFactory_Create(rclsid, riid, ppv, SchemaCache_create);
253     }
254     else if( IsEqualCLSID( rclsid, &CLSID_XMLDocument ) )
255     {
256         cf = &xmldoccf.IClassFactory_iface;
257     }
258     else if( IsEqualCLSID( rclsid, &CLSID_DOMFreeThreadedDocument )   ||   /* Version indep. v 2.x */
259              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument )   ||
260              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument26 ) ||
261              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument30 ) ||
262              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument40 ) ||
263              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument60 ))
264     {
265         return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
266     }
267     else if( IsEqualCLSID( rclsid, &CLSID_SAXXMLReader) ||
268              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader30 ) ||
269              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader40 ) ||
270              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader60 ))
271     {
272         cf = &saxreadcf.IClassFactory_iface;
273     }
274     else if( IsEqualCLSID( rclsid, &CLSID_XMLHTTPRequest ) ||
275              IsEqualCLSID( rclsid, &CLSID_XMLHTTP) ||
276              IsEqualCLSID( rclsid, &CLSID_XMLHTTP26 ) ||
277              IsEqualCLSID( rclsid, &CLSID_XMLHTTP30 ) ||
278              IsEqualCLSID( rclsid, &CLSID_XMLHTTP40 ) ||
279              IsEqualCLSID( rclsid, &CLSID_XMLHTTP60 ))
280     {
281         cf = &httpreqcf.IClassFactory_iface;
282     }
283     else if( IsEqualCLSID( rclsid, &CLSID_XSLTemplate )   ||
284              IsEqualCLSID( rclsid, &CLSID_XSLTemplate26 ) ||
285              IsEqualCLSID( rclsid, &CLSID_XSLTemplate30 ) ||
286              IsEqualCLSID( rclsid, &CLSID_XSLTemplate40 ) ||
287              IsEqualCLSID( rclsid, &CLSID_XSLTemplate60 ))
288     {
289         cf = &xsltemplatecf.IClassFactory_iface;
290     }
291     else if( IsEqualCLSID( rclsid, &CLSID_MXXMLWriter )   ||
292              IsEqualCLSID( rclsid, &CLSID_MXXMLWriter30 ) ||
293              IsEqualCLSID( rclsid, &CLSID_MXXMLWriter40 ) ||
294              IsEqualCLSID( rclsid, &CLSID_MXXMLWriter60 ) )
295     {
296         cf = &mxwritercf.IClassFactory_iface;
297     }
298
299     if ( !cf )
300         return CLASS_E_CLASSNOTAVAILABLE;
301
302     return IClassFactory_QueryInterface( cf, riid, ppv );
303 }