diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index 9053a7d27a9..8aa53323d02 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -77,7 +77,7 @@ typedef struct _domdoc VARIANT_BOOL validating; VARIANT_BOOL resolving; VARIANT_BOOL preserving; - BOOL bUseXPath; + BOOL XPath; IXMLDOMSchemaCollection *schema; bsc_t *bsc; HRESULT error; @@ -2139,9 +2139,9 @@ static HRESULT WINAPI domdoc_setProperty( hr = S_OK; if (lstrcmpiW(bstr, PropValueXPathW) == 0) - This->bUseXPath = TRUE; + This->XPath = TRUE; else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0) - This->bUseXPath = FALSE; + This->XPath = FALSE; else hr = E_FAIL; @@ -2180,7 +2180,7 @@ static HRESULT WINAPI domdoc_getProperty( if (lstrcmpiW(p, PropertySelectionLanguageW) == 0) { V_VT(var) = VT_BSTR; - if (This->bUseXPath) + if (This->XPath) V_BSTR(var) = SysAllocString(PropValueXPathW); else V_BSTR(var) = SysAllocString(PropValueXSLPatternW); @@ -2461,7 +2461,7 @@ HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **docu doc->validating = 0; doc->resolving = 0; doc->preserving = 0; - doc->bUseXPath = FALSE; + doc->XPath = FALSE; doc->error = S_OK; doc->schema = NULL; doc->stream = NULL; @@ -2477,7 +2477,7 @@ HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **docu return S_OK; } -HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj) +HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj) { xmlDocPtr xmldoc; HRESULT hr; @@ -2494,6 +2494,14 @@ HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj) if(FAILED(hr)) xmlFreeDoc(xmldoc); + /* properties that are dependent on object versions */ + if (IsEqualCLSID( clsid, &CLSID_DOMDocument40 ) || + IsEqualCLSID( clsid, &CLSID_DOMDocument60 )) + { + domdoc *This = impl_from_IXMLDOMDocument3(*ppObj); + This->XPath = TRUE; + } + return hr; } diff --git a/dlls/msxml3/factory.c b/dlls/msxml3/factory.c index 5e2039fee81..5c7d015135b 100644 --- a/dlls/msxml3/factory.c +++ b/dlls/msxml3/factory.c @@ -43,26 +43,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); -typedef HRESULT (*fnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); +typedef HRESULT (*ClassFactoryCreateInstanceFunc)(IUnknown *pUnkOuter, LPVOID *ppObj); +typedef HRESULT (*DOMFactoryCreateInstanceFunc)(const GUID *clsid, IUnknown *pUnkOuter, LPVOID *ppObj); /****************************************************************************** * MSXML ClassFactory */ -typedef struct _xmlcf +typedef struct { const struct IClassFactoryVtbl *lpVtbl; - fnCreateInstance pfnCreateInstance; -} xmlcf; + ClassFactoryCreateInstanceFunc pCreateInstance; +} ClassFactory; -static inline xmlcf *impl_from_IClassFactory( IClassFactory *iface ) +typedef struct { - return (xmlcf *)((char*)iface - FIELD_OFFSET(xmlcf, lpVtbl)); -} + const struct IClassFactoryVtbl *lpVtbl; + LONG ref; + DOMFactoryCreateInstanceFunc pCreateInstance; + GUID clsid; +} DOMFactory; -static HRESULT WINAPI xmlcf_QueryInterface( +static HRESULT WINAPI ClassFactory_QueryInterface( IClassFactory *iface, REFIID riid, - LPVOID *ppobj ) + void **ppobj ) { if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IClassFactory)) @@ -76,28 +80,26 @@ static HRESULT WINAPI xmlcf_QueryInterface( return E_NOINTERFACE; } -static ULONG WINAPI xmlcf_AddRef( - IClassFactory *iface ) +static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface ) { return 2; } -static ULONG WINAPI xmlcf_Release( - IClassFactory *iface ) +static ULONG WINAPI ClassFactory_Release(IClassFactory *iface ) { return 1; } -static HRESULT WINAPI xmlcf_CreateInstance( +static HRESULT WINAPI ClassFactory_CreateInstance( IClassFactory *iface, - LPUNKNOWN pOuter, + IUnknown *pOuter, REFIID riid, - LPVOID *ppobj ) + void **ppobj ) { - xmlcf *This = impl_from_IClassFactory( iface ); - HRESULT r; + ClassFactory *This = (ClassFactory*)iface; IUnknown *punk; - + HRESULT r; + TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj ); *ppobj = NULL; @@ -105,7 +107,7 @@ static HRESULT WINAPI xmlcf_CreateInstance( if (pOuter) return CLASS_E_NOAGGREGATION; - r = This->pfnCreateInstance( pOuter, (LPVOID*) &punk ); + r = This->pCreateInstance( pOuter, (void**) &punk ); if (FAILED(r)) return r; @@ -114,7 +116,7 @@ static HRESULT WINAPI xmlcf_CreateInstance( return r; } -static HRESULT WINAPI xmlcf_LockServer( +static HRESULT WINAPI ClassFactory_LockServer( IClassFactory *iface, BOOL dolock) { @@ -122,29 +124,100 @@ static HRESULT WINAPI xmlcf_LockServer( return S_OK; } -static const struct IClassFactoryVtbl xmlcf_vtbl = +static ULONG WINAPI DOMClassFactory_AddRef(IClassFactory *iface ) { - xmlcf_QueryInterface, - xmlcf_AddRef, - xmlcf_Release, - xmlcf_CreateInstance, - xmlcf_LockServer + DOMFactory *This = (DOMFactory*)iface; + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) ref = %u\n", This, ref); + return ref; +} + +static ULONG WINAPI DOMClassFactory_Release(IClassFactory *iface ) +{ + DOMFactory *This = (DOMFactory*)iface; + 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 ) +{ + DOMFactory *This = (DOMFactory*)iface; + IUnknown *punk; + HRESULT r; + + TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj ); + + *ppobj = NULL; + + if (pOuter) + return CLASS_E_NOAGGREGATION; + + r = This->pCreateInstance( &This->clsid, pOuter, (void**) &punk ); + if (FAILED(r)) + return r; + + r = IUnknown_QueryInterface( punk, riid, ppobj ); + IUnknown_Release( punk ); + return r; +} + +static const struct IClassFactoryVtbl ClassFactoryVtbl = +{ + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + ClassFactory_CreateInstance, + ClassFactory_LockServer }; -static xmlcf domdoccf = { &xmlcf_vtbl, DOMDocument_create }; -static xmlcf schemacf = { &xmlcf_vtbl, SchemaCache_create }; -static xmlcf xmldoccf = { &xmlcf_vtbl, XMLDocument_create }; -static xmlcf saxreadcf = { &xmlcf_vtbl, SAXXMLReader_create }; -static xmlcf httpreqcf = { &xmlcf_vtbl, XMLHTTPRequest_create }; +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; + + ret->lpVtbl = &DOMClassFactoryVtbl; + ret->ref = 0; + ret->clsid = *clsid; + ret->pCreateInstance = fnCreateInstance; + + hres = IClassFactory_QueryInterface((IClassFactory*)ret, riid, ppv); + if(FAILED(hres)) { + heap_free(ret); + *ppv = NULL; + } + return hres; +} + +static ClassFactory schemacf = { &ClassFactoryVtbl, SchemaCache_create }; +static ClassFactory xmldoccf = { &ClassFactoryVtbl, XMLDocument_create }; +static ClassFactory saxreadcf = { &ClassFactoryVtbl, SAXXMLReader_create }; +static ClassFactory httpreqcf = { &ClassFactoryVtbl, XMLHTTPRequest_create }; /****************************************************************** * DllGetClassObject (MSXML3.@) */ -HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID iid, LPVOID *ppv ) +HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv ) { IClassFactory *cf = NULL; - TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv ); + TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv ); if( IsEqualCLSID( rclsid, &CLSID_DOMDocument ) || /* Version indep. v 2.x */ IsEqualCLSID( rclsid, &CLSID_DOMDocument2 ) || /* Version indep. v 3.0 */ @@ -152,7 +225,7 @@ HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID iid, LPVOID *ppv ) IsEqualCLSID( rclsid, &CLSID_DOMDocument40 )|| /* Version dep. v 4.0 */ IsEqualCLSID( rclsid, &CLSID_DOMDocument60 )) /* Version dep. v 6.0 */ { - cf = (IClassFactory*) &domdoccf.lpVtbl; + return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create); } else if( IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache ) || IsEqualCLSID( rclsid, &CLSID_XMLSchemaCache30 ) || @@ -171,7 +244,7 @@ HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID iid, LPVOID *ppv ) IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument40 ) || IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument60 )) { - cf = (IClassFactory*) &domdoccf.lpVtbl; + return DOMClassFactory_Create(rclsid, riid, ppv, DOMDocument_create); } else if( IsEqualCLSID( rclsid, &CLSID_SAXXMLReader) || IsEqualCLSID( rclsid, &CLSID_SAXXMLReader30 ) || @@ -188,5 +261,5 @@ HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID iid, LPVOID *ppv ) if ( !cf ) return CLASS_E_CLASSNOTAVAILABLE; - return IClassFactory_QueryInterface( cf, iid, ppv ); + return IClassFactory_QueryInterface( cf, riid, ppv ); } diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index 830e45cc5be..a1b3b9d0389 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -244,11 +244,11 @@ MAKE_FUNCPTR(xsltParseStylesheetDoc); extern IXMLDOMParseError *create_parseError( LONG code, BSTR url, BSTR reason, BSTR srcText, LONG line, LONG linepos, LONG filepos ); -extern HRESULT DOMDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj ); -extern HRESULT SchemaCache_create( IUnknown *pUnkOuter, LPVOID *ppObj ); -extern HRESULT XMLDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj ); -extern HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj ); -extern HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj); +extern HRESULT DOMDocument_create( const GUID *clsid, IUnknown *pUnkOuter, void **ppObj ); +extern HRESULT SchemaCache_create( IUnknown *pUnkOuter, void **pObj ); +extern HRESULT XMLDocument_create( IUnknown *pUnkOuter, void **pObj ); +extern HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, void **pObj ); +extern HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **pObj); typedef struct bsc_t bsc_t; diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index cd789e58573..0ed8f338223 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -37,6 +37,7 @@ #include "initguid.h" DEFINE_GUID(IID_IObjectSafety, 0xcb5bdc81, 0x93c1, 0x11cf, 0x8f,0x20, 0x00,0x80,0x5f,0x2c,0xd0,0x64); +DEFINE_GUID(CLSID_DOMDocument60, 0x88d96a05, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5); static const WCHAR szEmpty[] = { 0 }; static const WCHAR szIncomplete[] = { @@ -5617,6 +5618,50 @@ static void test_document_IObjectSafety(void) IXMLDOMDocument_Release(doc); } +typedef struct _property_test_t { + const GUID *guid; + const char *clsid; + const char *property; + const char *value; +} property_test_t; + +static const property_test_t properties_test_data[] = { + { &CLSID_DOMDocument, "CLSID_DOMDocument" , "SelectionLanguage", "XSLPattern" }, + { &CLSID_DOMDocument2, "CLSID_DOMDocument2" , "SelectionLanguage", "XSLPattern" }, + { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "SelectionLanguage", "XSLPattern" }, + { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "SelectionLanguage", "XPath" }, + { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "SelectionLanguage", "XPath" }, + { 0 } +}; + +static void test_default_properties(void) +{ + const property_test_t *entry = properties_test_data; + IXMLDOMDocument2 *doc; + VARIANT var; + HRESULT hr; + + while (entry->guid) + { + hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc); + if (hr != S_OK) + { + win_skip("can't create %s instance\n", entry->clsid); + continue; + } + + hr = IXMLDOMDocument2_getProperty(doc, _bstr_(entry->property), &var); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(lstrcmpW(V_BSTR(&var), _bstr_(entry->value)) == 0, "expected %s, for %s\n", + entry->value, entry->clsid); + VariantClear(&var); + + IXMLDOMDocument2_Release(doc); + + entry++; + } +} + static void test_XSLPattern(void) { IXMLDOMDocument2 *doc; @@ -5630,7 +5675,7 @@ static void test_XSLPattern(void) ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b)); ok(b == VARIANT_TRUE, "failed to load XML string\n"); - /* switch to XPath */ + /* switch to XSLPattern */ ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern"))); /* XPath doesn't select elements with non-null default namespace with unqualified selectors, XSLPattern does */ @@ -6229,6 +6274,7 @@ START_TEST(domdoc) test_put_dataType(); test_createNode(); test_get_prefix(); + test_default_properties(); CoUninitialize(); }