factory.c 12.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 *    MSXML Class Factory
 *
 * Copyright 2002 Lionel Ulmer
 * Copyright 2005 Mike McCormack
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 23
 */

#define COBJMACROS

24 25
#include "config.h"

26
#include <stdarg.h>
27 28 29 30 31
#ifdef HAVE_LIBXML2
# include <libxml/parser.h>
# include <libxml/xmlerror.h>
#endif

32 33 34 35
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
36
#include "msxml.h"
37
#include "msxml2.h"
38
#include "xmlparser.h"
39

40 41 42 43
/* undef the #define in msxml2 so that we can access the v.2 version
   independent CLSID as well as the v.3 one. */
#undef CLSID_DOMDocument

44 45 46 47 48 49
#include "wine/debug.h"

#include "msxml_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(msxml);

50 51
typedef HRESULT (*ClassFactoryCreateInstanceFunc)(void**);
typedef HRESULT (*DOMFactoryCreateInstanceFunc)(MSXML_VERSION, void**);
52 53 54 55 56 57 58 59 60 61

struct clsid_version_t
{
    const GUID *clsid;
    MSXML_VERSION version;
};

static const struct clsid_version_t clsid_versions_table[] =
{
    { &CLSID_DOMDocument,   MSXML_DEFAULT },
62 63 64 65 66
    { &CLSID_DOMDocument2,  MSXML2  },
    { &CLSID_DOMDocument26, MSXML26 },
    { &CLSID_DOMDocument30, MSXML3  },
    { &CLSID_DOMDocument40, MSXML4  },
    { &CLSID_DOMDocument60, MSXML6  },
67 68 69

    { &CLSID_DOMFreeThreadedDocument,   MSXML_DEFAULT },
    { &CLSID_FreeThreadedDOMDocument,   MSXML_DEFAULT },
70 71 72 73
    { &CLSID_FreeThreadedDOMDocument26, MSXML26 },
    { &CLSID_FreeThreadedDOMDocument30, MSXML3  },
    { &CLSID_FreeThreadedDOMDocument40, MSXML4  },
    { &CLSID_FreeThreadedDOMDocument60, MSXML6  },
74 75

    { &CLSID_XMLSchemaCache,   MSXML_DEFAULT },
76 77 78 79
    { &CLSID_XMLSchemaCache26, MSXML26 },
    { &CLSID_XMLSchemaCache30, MSXML3  },
    { &CLSID_XMLSchemaCache40, MSXML4  },
    { &CLSID_XMLSchemaCache60, MSXML6  },
80 81 82 83

    { &CLSID_MXXMLWriter,   MSXML_DEFAULT },
    { &CLSID_MXXMLWriter30, MSXML3 },
    { &CLSID_MXXMLWriter40, MSXML4 },
84 85 86 87 88
    { &CLSID_MXXMLWriter60, MSXML6 },

    { &CLSID_SAXXMLReader,   MSXML_DEFAULT },
    { &CLSID_SAXXMLReader30, MSXML3 },
    { &CLSID_SAXXMLReader40, MSXML4 },
89 90 91 92 93
    { &CLSID_SAXXMLReader60, MSXML6 },

    { &CLSID_SAXAttributes,   MSXML_DEFAULT },
    { &CLSID_SAXAttributes30, MSXML3 },
    { &CLSID_SAXAttributes40, MSXML4 },
94 95 96
    { &CLSID_SAXAttributes60, MSXML6 },

    { &CLSID_XMLView, MSXML_DEFAULT }
97 98 99 100
};

static MSXML_VERSION get_msxml_version(const GUID *clsid)
{
101
    unsigned int i;
102 103 104 105 106 107 108 109

    for (i = 0; i < sizeof(clsid_versions_table)/sizeof(struct clsid_version_t); i++)
        if (IsEqualGUID(clsid, clsid_versions_table[i].clsid))
            return clsid_versions_table[i].version;

    ERR("unknown clsid=%s\n", debugstr_guid(clsid));
    return MSXML_DEFAULT;
}
110 111 112 113

/******************************************************************************
 * MSXML ClassFactory
 */
114
typedef struct
115
{
116
    IClassFactory IClassFactory_iface;
117 118
    ClassFactoryCreateInstanceFunc pCreateInstance;
} ClassFactory;
119

120
typedef struct
121
{
122
    IClassFactory IClassFactory_iface;
123 124
    LONG ref;
    DOMFactoryCreateInstanceFunc pCreateInstance;
125
    MSXML_VERSION version;
126
} DOMFactory;
127

128 129 130 131 132
static inline ClassFactory *ClassFactory_from_IClassFactory(IClassFactory *iface)
{
    return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
}

133
static HRESULT WINAPI ClassFactory_QueryInterface(
134 135
    IClassFactory *iface,
    REFIID riid,
136
    void **ppobj )
137 138 139 140 141 142 143 144 145
{
    if (IsEqualGUID(riid, &IID_IUnknown) ||
        IsEqualGUID(riid, &IID_IClassFactory))
    {
        IClassFactory_AddRef( iface );
        *ppobj = iface;
        return S_OK;
    }

146
    FIXME("interface %s not implemented\n", debugstr_guid(riid));
147
    *ppobj = NULL;
148 149 150
    return E_NOINTERFACE;
}

151
static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface )
152 153 154 155
{
    return 2;
}

156
static ULONG WINAPI ClassFactory_Release(IClassFactory *iface )
157 158 159 160
{
    return 1;
}

161
static HRESULT WINAPI ClassFactory_CreateInstance(
162
    IClassFactory *iface,
163
    IUnknown *pOuter,
164
    REFIID riid,
165
    void **ppobj )
166
{
167
    ClassFactory *This = ClassFactory_from_IClassFactory(iface);
168
    IUnknown *punk;
169 170
    HRESULT r;

171 172 173 174 175 176 177
    TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );

    *ppobj = NULL;

    if (pOuter)
        return CLASS_E_NOAGGREGATION;

178
    r = This->pCreateInstance( (void**) &punk );
179 180 181 182 183 184 185 186
    if (FAILED(r))
        return r;

    r = IUnknown_QueryInterface( punk, riid, ppobj );
    IUnknown_Release( punk );
    return r;
}

187
static HRESULT WINAPI ClassFactory_LockServer(
188 189 190 191 192 193 194
    IClassFactory *iface,
    BOOL dolock)
{
    FIXME("(%p)->(%d),stub!\n",iface,dolock);
    return S_OK;
}

195 196 197 198 199
static inline DOMFactory *DOMFactory_from_IClassFactory(IClassFactory *iface)
{
    return CONTAINING_RECORD(iface, DOMFactory, IClassFactory_iface);
}

200 201
static ULONG WINAPI DOMClassFactory_AddRef(IClassFactory *iface )
{
202
    DOMFactory *This = DOMFactory_from_IClassFactory(iface);
203 204 205 206 207 208 209
    ULONG ref = InterlockedIncrement(&This->ref);
    TRACE("(%p) ref = %u\n", This, ref);
    return ref;
}

static ULONG WINAPI DOMClassFactory_Release(IClassFactory *iface )
{
210
    DOMFactory *This = DOMFactory_from_IClassFactory(iface);
211 212 213 214 215 216 217 218 219 220 221 222 223 224
    ULONG ref = InterlockedDecrement(&This->ref);
    TRACE("(%p) ref = %u\n", This, ref);
    if(!ref) {
        heap_free(This);
    }
    return ref;
}

static HRESULT WINAPI DOMClassFactory_CreateInstance(
    IClassFactory *iface,
    IUnknown *pOuter,
    REFIID riid,
    void **ppobj )
{
225
    DOMFactory *This = DOMFactory_from_IClassFactory(iface);
226 227 228 229 230 231 232 233 234 235
    IUnknown *punk;
    HRESULT r;

    TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );

    *ppobj = NULL;

    if (pOuter)
        return CLASS_E_NOAGGREGATION;

236
    r = This->pCreateInstance( This->version, (void**) &punk );
237 238 239 240 241 242 243 244 245
    if (FAILED(r))
        return r;

    r = IUnknown_QueryInterface( punk, riid, ppobj );
    IUnknown_Release( punk );
    return r;
}

static const struct IClassFactoryVtbl ClassFactoryVtbl =
246
{
247 248 249 250 251
    ClassFactory_QueryInterface,
    ClassFactory_AddRef,
    ClassFactory_Release,
    ClassFactory_CreateInstance,
    ClassFactory_LockServer
252 253
};

254 255 256 257 258 259 260 261 262 263 264 265 266 267
static const struct IClassFactoryVtbl DOMClassFactoryVtbl =
{
    ClassFactory_QueryInterface,
    DOMClassFactory_AddRef,
    DOMClassFactory_Release,
    DOMClassFactory_CreateInstance,
    ClassFactory_LockServer
};

static HRESULT DOMClassFactory_Create(const GUID *clsid, REFIID riid, void **ppv, DOMFactoryCreateInstanceFunc fnCreateInstance)
{
    DOMFactory *ret = heap_alloc(sizeof(DOMFactory));
    HRESULT hres;

268
    ret->IClassFactory_iface.lpVtbl = &DOMClassFactoryVtbl;
269
    ret->ref = 0;
270
    ret->version = get_msxml_version(clsid);
271 272
    ret->pCreateInstance = fnCreateInstance;

273
    hres = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv);
274 275 276 277 278 279 280
    if(FAILED(hres)) {
        heap_free(ret);
        *ppv = NULL;
    }
    return hres;
}

281 282
static ClassFactory xmldoccf = { { &ClassFactoryVtbl }, XMLDocument_create };
static ClassFactory httpreqcf = { { &ClassFactoryVtbl }, XMLHTTPRequest_create };
283
static ClassFactory serverhttp = { { &ClassFactoryVtbl }, ServerXMLHTTP_create };
284
static ClassFactory xsltemplatecf = { { &ClassFactoryVtbl }, XSLTemplate_create };
285
static ClassFactory mxnsmanagercf = { {&ClassFactoryVtbl }, MXNamespaceManager_create };
286
static ClassFactory xmlparsercf = { { &ClassFactoryVtbl }, XMLParser_create };
287
static ClassFactory xmlviewcf = { { &ClassFactoryVtbl }, XMLView_create };
288

289 290 291
/******************************************************************
 *		DllGetClassObject (MSXML3.@)
 */
292
HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
293 294 295
{
    IClassFactory *cf = NULL;

296
    TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv );
297

298
    if( IsEqualCLSID( rclsid, &CLSID_DOMDocument )  ||  /* Version indep. v 2.x */
299
        IsEqualCLSID( rclsid, &CLSID_DOMDocument2 ) ||  /* Version indep. v 3.0 */
300
        IsEqualCLSID( rclsid, &CLSID_DOMDocument26 )||  /* Version dep.   v 2.6 */
301
        IsEqualCLSID( rclsid, &CLSID_DOMDocument30 )||  /* Version dep.   v 3.0 */
302 303
        IsEqualCLSID( rclsid, &CLSID_DOMDocument40 )||  /* Version dep.   v 4.0 */
        IsEqualCLSID( rclsid, &CLSID_DOMDocument60 ))   /* Version dep.   v 6.0 */
304
    {
305
        return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
306
    }
307
    else if( IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache )   ||
308
             IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache26 ) ||
309 310 311
             IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache30 ) ||
             IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache40 ) ||
             IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache60 ))
312
    {
313
        return DOMClassFactory_Create(rclsid, riid, ppv, SchemaCache_create);
314 315 316
    }
    else if( IsEqualCLSID( rclsid, &CLSID_XMLDocument ) )
    {
317
        cf = &xmldoccf.IClassFactory_iface;
318
    }
319 320
    else if( IsEqualCLSID( rclsid, &CLSID_DOMFreeThreadedDocument )   ||   /* Version indep. v 2.x */
             IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument )   ||
321
             IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument26 ) ||
322
             IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument30 ) ||
323
             IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument40 ) ||
324
             IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument60 ))
325
    {
326
        return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create);
327
    }
328
    else if( IsEqualCLSID( rclsid, &CLSID_SAXXMLReader) ||
329
             IsEqualCLSID( rclsid, &CLSID_SAXXMLReader30 ) ||
330 331
             IsEqualCLSID( rclsid, &CLSID_SAXXMLReader40 ) ||
             IsEqualCLSID( rclsid, &CLSID_SAXXMLReader60 ))
332
    {
333
        return DOMClassFactory_Create(rclsid, riid, ppv, SAXXMLReader_create);
334
    }
335
    else if( IsEqualCLSID( rclsid, &CLSID_XMLHTTPRequest ) ||
336
             IsEqualCLSID( rclsid, &CLSID_XMLHTTP) ||
337 338 339 340
             IsEqualCLSID( rclsid, &CLSID_XMLHTTP26 ) ||
             IsEqualCLSID( rclsid, &CLSID_XMLHTTP30 ) ||
             IsEqualCLSID( rclsid, &CLSID_XMLHTTP40 ) ||
             IsEqualCLSID( rclsid, &CLSID_XMLHTTP60 ))
341
    {
342
        cf = &httpreqcf.IClassFactory_iface;
343
    }
344 345 346 347 348 349 350
    else if( IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP ) ||
             IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP30 ) ||
             IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP40 ) ||
             IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP60 ))
    {
        cf = &serverhttp.IClassFactory_iface;
    }
351 352 353 354 355 356
    else if( IsEqualCLSID( rclsid, &CLSID_XSLTemplate )   ||
             IsEqualCLSID( rclsid, &CLSID_XSLTemplate26 ) ||
             IsEqualCLSID( rclsid, &CLSID_XSLTemplate30 ) ||
             IsEqualCLSID( rclsid, &CLSID_XSLTemplate40 ) ||
             IsEqualCLSID( rclsid, &CLSID_XSLTemplate60 ))
    {
357
        cf = &xsltemplatecf.IClassFactory_iface;
358
    }
359 360 361 362 363
    else if( IsEqualCLSID( rclsid, &CLSID_MXXMLWriter )   ||
             IsEqualCLSID( rclsid, &CLSID_MXXMLWriter30 ) ||
             IsEqualCLSID( rclsid, &CLSID_MXXMLWriter40 ) ||
             IsEqualCLSID( rclsid, &CLSID_MXXMLWriter60 ) )
    {
364
        return DOMClassFactory_Create(rclsid, riid, ppv, MXWriter_create);
365
    }
366 367 368 369 370 371 372
    else if( IsEqualCLSID( rclsid, &CLSID_SAXAttributes) ||
             IsEqualCLSID( rclsid, &CLSID_SAXAttributes30 ) ||
             IsEqualCLSID( rclsid, &CLSID_SAXAttributes40 ) ||
             IsEqualCLSID( rclsid, &CLSID_SAXAttributes60 ))
    {
        return DOMClassFactory_Create(rclsid, riid, ppv, SAXAttributes_create);
    }
373 374 375 376 377 378
    else if( IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager ) ||
             IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager40 ) ||
             IsEqualCLSID( rclsid, &CLSID_MXNamespaceManager60 ) )
    {
        cf = &mxnsmanagercf.IClassFactory_iface;
    }
379 380 381 382 383 384
    else if( IsEqualCLSID( rclsid, &CLSID_XMLParser )  ||
             IsEqualCLSID( rclsid, &CLSID_XMLParser26 ) ||
             IsEqualCLSID( rclsid, &CLSID_XMLParser30 )  )
    {
        cf = &xmlparsercf.IClassFactory_iface;
    }
385 386 387 388
    else if( IsEqualCLSID( rclsid, &CLSID_XMLView ) )
    {
        cf = &xmlviewcf.IClassFactory_iface;
    }
389

390 391 392
    if ( !cf )
        return CLASS_E_CLASSNOTAVAILABLE;

393
    return IClassFactory_QueryInterface( cf, riid, ppv );
394
}