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