msxml2: Add an msxml2 library that contains the v2.6 msxml typelib.
[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 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "ole2.h"
31 #include "msxml.h"
32 #include "msxml2.h"
33
34 /* undef the #define in msxml2 so that we can access the v.2 version
35    independent CLSID as well as the v.3 one. */
36 #undef CLSID_DOMDocument
37
38 #include "wine/debug.h"
39
40 #include "msxml_private.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43
44 typedef HRESULT (*ClassFactoryCreateInstanceFunc)(IUnknown *pUnkOuter, LPVOID *ppObj);
45 typedef HRESULT (*DOMFactoryCreateInstanceFunc)(const GUID *clsid, IUnknown *pUnkOuter, LPVOID *ppObj);
46
47 /******************************************************************************
48  * MSXML ClassFactory
49  */
50 typedef struct
51 {
52     const struct IClassFactoryVtbl *lpVtbl;
53     ClassFactoryCreateInstanceFunc pCreateInstance;
54 } ClassFactory;
55
56 typedef struct
57 {
58     const struct IClassFactoryVtbl *lpVtbl;
59     LONG ref;
60     DOMFactoryCreateInstanceFunc pCreateInstance;
61     GUID clsid;
62 } DOMFactory;
63
64 static HRESULT WINAPI ClassFactory_QueryInterface(
65     IClassFactory *iface,
66     REFIID riid,
67     void **ppobj )
68 {
69     if (IsEqualGUID(riid, &IID_IUnknown) ||
70         IsEqualGUID(riid, &IID_IClassFactory))
71     {
72         IClassFactory_AddRef( iface );
73         *ppobj = iface;
74         return S_OK;
75     }
76
77     FIXME("interface %s not implemented\n", debugstr_guid(riid));
78     return E_NOINTERFACE;
79 }
80
81 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface )
82 {
83     return 2;
84 }
85
86 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface )
87 {
88     return 1;
89 }
90
91 static HRESULT WINAPI ClassFactory_CreateInstance(
92     IClassFactory *iface,
93     IUnknown *pOuter,
94     REFIID riid,
95     void **ppobj )
96 {
97     ClassFactory *This = (ClassFactory*)iface;
98     IUnknown *punk;
99     HRESULT r;
100
101     TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
102
103     *ppobj = NULL;
104
105     if (pOuter)
106         return CLASS_E_NOAGGREGATION;
107
108     r = This->pCreateInstance( pOuter, (void**) &punk );
109     if (FAILED(r))
110         return r;
111
112     r = IUnknown_QueryInterface( punk, riid, ppobj );
113     IUnknown_Release( punk );
114     return r;
115 }
116
117 static HRESULT WINAPI ClassFactory_LockServer(
118     IClassFactory *iface,
119     BOOL dolock)
120 {
121     FIXME("(%p)->(%d),stub!\n",iface,dolock);
122     return S_OK;
123 }
124
125 static ULONG WINAPI DOMClassFactory_AddRef(IClassFactory *iface )
126 {
127     DOMFactory *This = (DOMFactory*)iface;
128     ULONG ref = InterlockedIncrement(&This->ref);
129     TRACE("(%p) ref = %u\n", This, ref);
130     return ref;
131 }
132
133 static ULONG WINAPI DOMClassFactory_Release(IClassFactory *iface )
134 {
135     DOMFactory *This = (DOMFactory*)iface;
136     ULONG ref = InterlockedDecrement(&This->ref);
137     TRACE("(%p) ref = %u\n", This, ref);
138     if(!ref) {
139         heap_free(This);
140     }
141     return ref;
142 }
143
144 static HRESULT WINAPI DOMClassFactory_CreateInstance(
145     IClassFactory *iface,
146     IUnknown *pOuter,
147     REFIID riid,
148     void **ppobj )
149 {
150     DOMFactory *This = (DOMFactory*)iface;
151     IUnknown *punk;
152     HRESULT r;
153
154     TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
155
156     *ppobj = NULL;
157
158     if (pOuter)
159         return CLASS_E_NOAGGREGATION;
160
161     r = This->pCreateInstance( &This->clsid, pOuter, (void**) &punk );
162     if (FAILED(r))
163         return r;
164
165     r = IUnknown_QueryInterface( punk, riid, ppobj );
166     IUnknown_Release( punk );
167     return r;
168 }
169
170 static const struct IClassFactoryVtbl ClassFactoryVtbl =
171 {
172     ClassFactory_QueryInterface,
173     ClassFactory_AddRef,
174     ClassFactory_Release,
175     ClassFactory_CreateInstance,
176     ClassFactory_LockServer
177 };
178
179 static const struct IClassFactoryVtbl DOMClassFactoryVtbl =
180 {
181     ClassFactory_QueryInterface,
182     DOMClassFactory_AddRef,
183     DOMClassFactory_Release,
184     DOMClassFactory_CreateInstance,
185     ClassFactory_LockServer
186 };
187
188 static HRESULT DOMClassFactory_Create(const GUID *clsid, REFIID riid, void **ppv, DOMFactoryCreateInstanceFunc fnCreateInstance)
189 {
190     DOMFactory *ret = heap_alloc(sizeof(DOMFactory));
191     HRESULT hres;
192
193     ret->lpVtbl = &DOMClassFactoryVtbl;
194     ret->ref = 0;
195     ret->clsid = *clsid;
196     ret->pCreateInstance = fnCreateInstance;
197
198     hres = IClassFactory_QueryInterface((IClassFactory*)ret, riid, ppv);
199     if(FAILED(hres)) {
200         heap_free(ret);
201         *ppv = NULL;
202     }
203     return hres;
204 }
205
206 static ClassFactory xmldoccf = { &ClassFactoryVtbl, XMLDocument_create };
207 static ClassFactory saxreadcf = { &ClassFactoryVtbl, SAXXMLReader_create };
208 static ClassFactory httpreqcf = { &ClassFactoryVtbl, XMLHTTPRequest_create };
209
210 /******************************************************************
211  *              DllGetClassObject (MSXML3.@)
212  */
213 HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
214 {
215     IClassFactory *cf = NULL;
216
217     TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv );
218
219     if( IsEqualCLSID( rclsid, &CLSID_DOMDocument )  ||  /* Version indep. v 2.x */
220         IsEqualCLSID( rclsid, &CLSID_DOMDocument2 ) ||  /* Version indep. v 3.0 */
221         IsEqualCLSID( rclsid, &CLSID_DOMDocument26 )||  /* Version dep.   v 2.6 */
222         IsEqualCLSID( rclsid, &CLSID_DOMDocument30 )||  /* Version dep.   v 3.0 */
223         IsEqualCLSID( rclsid, &CLSID_DOMDocument40 )||  /* Version dep.   v 4.0 */
224         IsEqualCLSID( rclsid, &CLSID_DOMDocument60 ))   /* Version dep.   v 6.0 */
225     {
226         return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
227     }
228     else if( IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache )   ||
229              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache26 ) ||
230              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache30 ) ||
231              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache40 ) ||
232              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache60 ))
233     {
234         return DOMClassFactory_Create(rclsid, riid, ppv, SchemaCache_create);
235     }
236     else if( IsEqualCLSID( rclsid, &CLSID_XMLDocument ) )
237     {
238         cf = (IClassFactory*) &xmldoccf.lpVtbl;
239     }
240     else if( IsEqualCLSID( rclsid, &CLSID_DOMFreeThreadedDocument )   ||   /* Version indep. v 2.x */
241              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument )   ||
242              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument26 ) ||
243              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument30 ) ||
244              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument40 ) ||
245              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument60 ))
246     {
247         return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
248     }
249     else if( IsEqualCLSID( rclsid, &CLSID_SAXXMLReader) ||
250              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader30 ) ||
251              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader40 ) ||
252              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader60 ))
253     {
254         cf = (IClassFactory*) &saxreadcf.lpVtbl;
255     }
256     else if( IsEqualCLSID( rclsid, &CLSID_XMLHTTPRequest ) ||
257              IsEqualCLSID( rclsid, &CLSID_XMLHTTP26 ) ||
258              IsEqualCLSID( rclsid, &CLSID_XMLHTTP30 ) ||
259              IsEqualCLSID( rclsid, &CLSID_XMLHTTP40 ) ||
260              IsEqualCLSID( rclsid, &CLSID_XMLHTTP60 ))
261     {
262         cf = (IClassFactory*) &httpreqcf.lpVtbl;
263     }
264
265     if ( !cf )
266         return CLASS_E_CLASSNOTAVAILABLE;
267
268     return IClassFactory_QueryInterface( cf, riid, ppv );
269 }