msxml: Added support to create msxml4/6 interfaces.
[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 #include "msxml6.h"
35
36 /* undef the #define in msxml2 so that we can access the v.2 version
37    independent CLSID as well as the v.3 one. */
38 #undef CLSID_DOMDocument
39
40 #include "wine/debug.h"
41
42 #include "msxml_private.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
45
46 typedef HRESULT (*fnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
47
48 /******************************************************************************
49  * MSXML ClassFactory
50  */
51 typedef struct _xmlcf
52 {
53     const struct IClassFactoryVtbl *lpVtbl;
54     fnCreateInstance pfnCreateInstance;
55 } xmlcf;
56
57 static inline xmlcf *impl_from_IClassFactory( IClassFactory *iface )
58 {
59     return (xmlcf *)((char*)iface - FIELD_OFFSET(xmlcf, lpVtbl));
60 }
61
62 static HRESULT WINAPI xmlcf_QueryInterface(
63     IClassFactory *iface,
64     REFIID riid,
65     LPVOID *ppobj )
66 {
67     if (IsEqualGUID(riid, &IID_IUnknown) ||
68         IsEqualGUID(riid, &IID_IClassFactory))
69     {
70         IClassFactory_AddRef( iface );
71         *ppobj = iface;
72         return S_OK;
73     }
74
75     FIXME("interface %s not implemented\n", debugstr_guid(riid));
76     return E_NOINTERFACE;
77 }
78
79 static ULONG WINAPI xmlcf_AddRef(
80     IClassFactory *iface )
81 {
82     return 2;
83 }
84
85 static ULONG WINAPI xmlcf_Release(
86     IClassFactory *iface )
87 {
88     return 1;
89 }
90
91 static HRESULT WINAPI xmlcf_CreateInstance(
92     IClassFactory *iface,
93     LPUNKNOWN pOuter,
94     REFIID riid,
95     LPVOID *ppobj )
96 {
97     xmlcf *This = impl_from_IClassFactory( iface );
98     HRESULT r;
99     IUnknown *punk;
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->pfnCreateInstance( pOuter, (LPVOID*) &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 xmlcf_LockServer(
118     IClassFactory *iface,
119     BOOL dolock)
120 {
121     FIXME("(%p)->(%d),stub!\n",iface,dolock);
122     return S_OK;
123 }
124
125 static const struct IClassFactoryVtbl xmlcf_vtbl =
126 {
127     xmlcf_QueryInterface,
128     xmlcf_AddRef,
129     xmlcf_Release,
130     xmlcf_CreateInstance,
131     xmlcf_LockServer
132 };
133
134 static xmlcf domdoccf = { &xmlcf_vtbl, DOMDocument_create };
135 static xmlcf schemacf = { &xmlcf_vtbl, SchemaCache_create };
136 static xmlcf xmldoccf = { &xmlcf_vtbl, XMLDocument_create };
137 static xmlcf saxreadcf = { &xmlcf_vtbl, SAXXMLReader_create };
138 static xmlcf httpreqcf = { &xmlcf_vtbl, XMLHTTPRequest_create };
139
140 /******************************************************************
141  *              DllGetClassObject (MSXML3.@)
142  */
143 HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID iid, LPVOID *ppv )
144 {
145     IClassFactory *cf = NULL;
146
147     TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv );
148
149     if( IsEqualCLSID( rclsid, &CLSID_DOMDocument )  ||  /* Version indep. v 2.x */
150         IsEqualCLSID( rclsid, &CLSID_DOMDocument2 ) ||  /* Version indep. v 3.0 */
151         IsEqualCLSID( rclsid, &CLSID_DOMDocument30 )||  /* Version dep.   v 3.0 */
152         IsEqualCLSID( rclsid, &CLSID_DOMDocument40 )||  /* Version dep.   v 4.0 */
153         IsEqualCLSID( rclsid, &CLSID_DOMDocument60 ))   /* Version dep.   v 6.0 */
154     {
155         cf = (IClassFactory*) &domdoccf.lpVtbl;
156     }
157     else if( IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache )   ||
158              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache30 ) ||
159              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache40 ) ||
160              IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache60 ))
161     {
162         cf = (IClassFactory*) &schemacf.lpVtbl;
163     }
164     else if( IsEqualCLSID( rclsid, &CLSID_XMLDocument ) )
165     {
166         cf = (IClassFactory*) &xmldoccf.lpVtbl;
167     }
168     else if( IsEqualCLSID( rclsid, &CLSID_DOMFreeThreadedDocument )   ||   /* Version indep. v 2.x */
169              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument )   ||
170              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument30 ) ||
171              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument40 ) ||
172              IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument60 ))
173     {
174         cf = (IClassFactory*) &domdoccf.lpVtbl;
175     }
176     else if( IsEqualCLSID( rclsid, &CLSID_SAXXMLReader) ||
177              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader30 ) ||
178              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader40 ) ||
179              IsEqualCLSID( rclsid, &CLSID_SAXXMLReader60 ))
180     {
181         cf = (IClassFactory*) &saxreadcf.lpVtbl;
182     }
183     else if( IsEqualCLSID( rclsid, &CLSID_XMLHTTPRequest))
184     {
185         cf = (IClassFactory*) &httpreqcf.lpVtbl;
186     }
187
188     if ( !cf )
189         return CLASS_E_CLASSNOTAVAILABLE;
190
191     return IClassFactory_QueryInterface( cf, iid, ppv );
192 }