static HRESULT WINAPI schema_cache_addCollection(IXMLDOMSchemaCollection2* iface, IXMLDOMSchemaCollection* otherCollection) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); schema_cache* That = impl_from_IXMLDOMSchemaCollection2((IXMLDOMSchemaCollection2*)otherCollection); TRACE("(%p)->(%p)\n", This, That); if (!otherCollection) return E_POINTER; /* TODO: detect errors while copying & return E_FAIL */ xmlHashScan(That->cache, cache_copy, This); return S_OK; }
XDR_DT SchemaCache_get_node_dt(IXMLDOMSchemaCollection2* iface, xmlNodePtr node) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); xmlSchemaPtr schema = get_node_schema(This, node); XDR_DT dt = DT_INVALID; TRACE("(%p, %p)\n", This, node); if (node->ns && xmlStrEqual(node->ns->href, DT_nsURI)) { dt = str_to_dt(node->name, -1); } else if (schema) { xmlChar* str; xmlNodePtr schema_node = lookup_schema_element(schema, node); str = xmlGetNsProp(schema_node, BAD_CAST "dt", DT_nsURI); if (str) { dt = str_to_dt(str, -1); xmlFree(str); } } return dt; }
static ULONG WINAPI schema_cache_AddRef(IXMLDOMSchemaCollection2* iface) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("%p new ref %d\n", This, ref); return ref; }
static HRESULT WINAPI schema_cache_get(IXMLDOMSchemaCollection2* iface, BSTR uri, IXMLDOMNode** node) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); cache_entry* entry; xmlChar* name; TRACE("(%p)->(%s %p)\n", This, debugstr_w(uri), node); if (This->version == MSXML6) { if (node) *node = NULL; return E_NOTIMPL; } if (!node) return E_POINTER; *node = NULL; name = uri ? xmlchar_from_wchar(uri) : xmlchar_from_wchar(emptyW); entry = (cache_entry*) xmlHashLookup(This->cache, name); heap_free(name); /* TODO: this should be read-only */ if (entry && entry->doc) return get_domdoc_from_xmldoc(entry->doc, (IXMLDOMDocument3**)node); return S_OK; }
static HRESULT WINAPI schema_cache_GetTypeInfo(IXMLDOMSchemaCollection2* iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); }
static HRESULT WINAPI schema_cache_QueryInterface(IXMLDOMSchemaCollection2* iface, REFIID riid, void** ppvObject) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); if ( IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) || IsEqualIID(riid, &IID_IXMLDOMSchemaCollection) || IsEqualIID(riid, &IID_IXMLDOMSchemaCollection2) ) { *ppvObject = iface; } else if (dispex_query_interface(&This->dispex, riid, ppvObject)) { return *ppvObject ? S_OK : E_NOINTERFACE; } else if(IsEqualGUID( riid, &IID_ISupportErrorInfo )) { return node_create_supporterrorinfo(schema_cache_se_tids, ppvObject); } else { FIXME("interface %s not implemented\n", debugstr_guid(riid)); *ppvObject = NULL; return E_NOINTERFACE; } IXMLDOMSchemaCollection2_AddRef(iface); return S_OK; }
static HRESULT WINAPI schema_cache_QueryInterface(IXMLDOMSchemaCollection2* iface, REFIID riid, void** ppvObject) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); if ( IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) || IsEqualIID(riid, &IID_IXMLDOMSchemaCollection) || IsEqualIID(riid, &IID_IXMLDOMSchemaCollection2) ) { *ppvObject = iface; } else { FIXME("interface %s not implemented\n", debugstr_guid(riid)); *ppvObject = NULL; return E_NOINTERFACE; } IXMLDOMSchemaCollection2_AddRef(iface); return S_OK; }
static HRESULT WINAPI schema_cache_GetIDsOfNames(IXMLDOMSchemaCollection2* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames, lcid, rgDispId); }
static HRESULT WINAPI schema_cache_getDeclaration(IXMLDOMSchemaCollection2* iface, IXMLDOMNode* node, ISchemaItem** item) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); FIXME("(%p)->(%p %p): stub\n", This, node, item); if (item) *item = NULL; return E_NOTIMPL; }
static HRESULT WINAPI schema_cache_getSchema(IXMLDOMSchemaCollection2* iface, BSTR namespaceURI, ISchema** schema) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), schema); if (schema) *schema = NULL; return E_NOTIMPL; }
static HRESULT WINAPI schema_cache_remove(IXMLDOMSchemaCollection2* iface, BSTR uri) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); xmlChar* name = xmlChar_from_wchar(uri); TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(uri)); xmlHashRemoveEntry(This->cache, name, cache_free); heap_free(name); return S_OK; }
static HRESULT WINAPI schema_cache_get_length(IXMLDOMSchemaCollection2* iface, LONG* length) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); TRACE("(%p)->(%p)\n", This, length); if (!length) return E_POINTER; *length = xmlHashSize(This->cache); return S_OK; }
static HRESULT WINAPI schema_cache_Invoke(IXMLDOMSchemaCollection2* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); }
HRESULT SchemaCache_validate_tree(IXMLDOMSchemaCollection2* iface, xmlNodePtr tree) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); cache_entry* entry; xmlChar const* ns = NULL; TRACE("(%p, %p)\n", This, tree); if (!tree) return E_POINTER; if ((xmlNodePtr)tree->doc == tree) { xmlNodePtr root = xmlDocGetRootElement(tree->doc); if (root && root->ns) ns = root->ns->href; } else if (tree->ns) { ns = tree->ns->href; } entry = xmlHashLookup(This->cache, ns); /* TODO: if the ns is not in the cache, and it's a URL, * do we try to load from that? */ if (entry) { if (entry->type == SCHEMA_TYPE_XDR) { FIXME("partial stub: XDR schema support not implemented\n"); return S_OK; } else if (entry->type == SCHEMA_TYPE_XSD) { xmlSchemaValidCtxtPtr svctx; int err; /* TODO: if validateOnLoad property is false, * we probably need to validate the schema here. */ svctx = xmlSchemaNewValidCtxt(entry->schema); xmlSchemaSetValidErrors(svctx, validate_error, validate_warning, NULL); #ifdef HAVE_XMLSCHEMASSETVALIDSTRUCTUREDERRORS xmlSchemaSetValidStructuredErrors(svctx, validate_serror, NULL); #endif if ((xmlNodePtr)tree->doc == tree) err = xmlSchemaValidateDoc(svctx, (xmlDocPtr)tree); else err = xmlSchemaValidateOneElement(svctx, tree); xmlSchemaFreeValidCtxt(svctx); return err? S_FALSE : S_OK; } } return E_FAIL; }
static HRESULT WINAPI schema_cache_GetTypeInfoCount(IXMLDOMSchemaCollection2* iface, UINT* pctinfo) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); TRACE("(%p)->(%p)\n", This, pctinfo); *pctinfo = 1; return S_OK; }
static HRESULT WINAPI schema_cache_get_validateOnLoad(IXMLDOMSchemaCollection2* iface, VARIANT_BOOL* value) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); TRACE("(%p)->(%p)\n", This, value); if (!value) return E_POINTER; *value = This->validateOnLoad; return S_OK; }
static HRESULT WINAPI schema_cache_remove(IXMLDOMSchemaCollection2* iface, BSTR uri) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); xmlChar* name = uri ? xmlchar_from_wchar(uri) : xmlchar_from_wchar(emptyW); TRACE("(%p)->(%s)\n", This, debugstr_w(uri)); if (This->version == MSXML6) return E_NOTIMPL; cache_remove_entry(This, name); heap_free(name); return S_OK; }
static HRESULT WINAPI schema_cache_GetTypeInfo(IXMLDOMSchemaCollection2* iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); HRESULT hr; TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); hr = get_typeinfo(IXMLDOMSchemaCollection_tid, ppTInfo); return hr; }
static HRESULT WINAPI schema_cache_put_validateOnLoad(IXMLDOMSchemaCollection2* iface, VARIANT_BOOL value) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); FIXME("(%p)->(%d): stub\n", This, value); This->validateOnLoad = value; /* it's ok to disable it, cause we don't validate on load anyway */ if (value == VARIANT_FALSE) return S_OK; return E_NOTIMPL; }
/* This one adds all namespaces defined in document to a cache, without anything associated with uri obviously. Unfortunately namespace:: axis implementation in libxml2 differs from what we need, it uses additional node type to describe namespace definition attribute while in msxml it's expected to be a normal attribute - as a workaround document is queried at libxml2 level here. */ HRESULT cache_from_doc_ns(IXMLDOMSchemaCollection2 *iface, xmlnode *node) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); static const xmlChar query[] = "//*/namespace::*"; xmlXPathObjectPtr nodeset; xmlXPathContextPtr ctxt; This->read_only = 1; ctxt = xmlXPathNewContext(node->node->doc); nodeset = xmlXPathEvalExpression(query, ctxt); xmlXPathFreeContext(ctxt); if (nodeset) { int pos = 0, len = xmlXPathNodeSetGetLength(nodeset->nodesetval); if (len == 0) return S_OK; while (pos < len) { xmlNodePtr node = xmlXPathNodeSetItem(nodeset->nodesetval, pos); if (node->type == XML_NAMESPACE_DECL) { static const xmlChar defns[] = "http://www.w3.org/XML/1998/namespace"; xmlNsPtr ns = (xmlNsPtr)node; cache_entry *entry; /* filter out default uri */ if (xmlStrEqual(ns->href, defns)) { pos++; continue; } entry = heap_alloc(sizeof(cache_entry)); entry->type = CacheEntryType_NS; entry->ref = 1; entry->schema = NULL; entry->doc = NULL; cache_add_entry(This, ns->href, entry); } pos++; } xmlXPathFreeObject(nodeset); } return S_OK; }
static ULONG WINAPI schema_cache_Release(IXMLDOMSchemaCollection2* iface) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("%p new ref %d\n", This, ref); if (ref == 0) { xmlHashFree(This->cache, cache_free); heap_free(This); } return ref; }
static HRESULT WINAPI schema_cache_get_namespaceURI(IXMLDOMSchemaCollection2* iface, LONG index, BSTR* len) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); cache_index_data data = {index,len}; TRACE("(%p)->(%i, %p)\n", This, index, len); if (!len) return E_POINTER; *len = NULL; if (index >= xmlHashSize(This->cache)) return E_FAIL; xmlHashScan(This->cache, cache_index, &data); return S_OK; }
static ULONG WINAPI schema_cache_Release(IXMLDOMSchemaCollection2* iface) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)->(%d)\n", This, ref); if (ref == 0) { int i; for (i = 0; i < This->count; i++) heap_free(This->uris[i]); heap_free(This->uris); xmlHashFree(This->cache, cache_free); heap_free(This); } return ref; }
static HRESULT WINAPI schema_cache_get_namespaceURI(IXMLDOMSchemaCollection2* iface, LONG index, BSTR* uri) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); TRACE("(%p)->(%i %p)\n", This, index, uri); if (!uri) return E_POINTER; if (This->version == MSXML6) *uri = NULL; if (index >= This->count) return E_FAIL; *uri = bstr_from_xmlChar(This->uris[index]); return S_OK; }
static HRESULT WINAPI schema_cache_get(IXMLDOMSchemaCollection2* iface, BSTR uri, IXMLDOMNode** node) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); xmlChar* name; cache_entry* entry; TRACE("(%p)->(%s, %p)\n", This, wine_dbgstr_w(uri), node); if (!node) return E_POINTER; name = xmlChar_from_wchar(uri); entry = (cache_entry*) xmlHashLookup(This->cache, name); heap_free(name); /* TODO: this should be read-only */ if (entry) return DOMDocument_create_from_xmldoc(entry->doc, (IXMLDOMDocument3**)node); *node = NULL; return S_OK; }
HRESULT SchemaCache_validate_tree(IXMLDOMSchemaCollection2* iface, xmlNodePtr tree) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); xmlSchemaPtr schema; TRACE("(%p, %p)\n", This, tree); if (!tree) return E_POINTER; if (tree->type == XML_DOCUMENT_NODE) tree = xmlDocGetRootElement(tree->doc); schema = get_node_schema(This, tree); /* TODO: if the ns is not in the cache, and it's a URL, * do we try to load from that? */ if (schema) return Schema_validate_tree(schema, tree); else WARN("no schema found for xmlns=%s\n", get_node_nsURI(tree)); return E_FAIL; }
static HRESULT WINAPI schema_cache_Invoke(IXMLDOMSchemaCollection2* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); ITypeInfo* typeinfo; HRESULT hr; TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); hr = get_typeinfo(IXMLDOMSchemaCollection_tid, &typeinfo); if(SUCCEEDED(hr)) { hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); ITypeInfo_Release(typeinfo); } return hr; }
static HRESULT WINAPI schema_cache_GetIDsOfNames(IXMLDOMSchemaCollection2* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); ITypeInfo* typeinfo; HRESULT hr; TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); if(!rgszNames || cNames == 0 || !rgDispId) return E_INVALIDARG; hr = get_typeinfo(IXMLDOMSchemaCollection_tid, &typeinfo); if(SUCCEEDED(hr)) { hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); ITypeInfo_Release(typeinfo); } return hr; }
static HRESULT WINAPI schema_cache_addCollection(IXMLDOMSchemaCollection2* iface, IXMLDOMSchemaCollection* collection) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); schema_cache* That; TRACE("(%p)->(%p)\n", This, collection); if (!collection) return E_POINTER; That = unsafe_impl_from_IXMLDOMSchemaCollection(collection); if (!That) { ERR("external collection implementation\n"); return E_FAIL; } /* TODO: detect errors while copying & return E_FAIL */ xmlHashScan(That->cache, cache_copy, This); return S_OK; }
static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri, VARIANT var) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); xmlChar* name = xmlChar_from_wchar(uri); TRACE("(%p)->(%s, var(vt %x))\n", This, debugstr_w(uri), V_VT(&var)); switch (V_VT(&var)) { case VT_NULL: { xmlHashRemoveEntry(This->cache, name, cache_free); } break; case VT_BSTR: { xmlChar* url = xmlChar_from_wchar(V_BSTR(&var)); cache_entry* entry = cache_entry_from_url((char const*)url); heap_free(url); if (entry) { cache_entry_add_ref(entry); } else { heap_free(name); return E_FAIL; } xmlHashRemoveEntry(This->cache, name, cache_free); xmlHashAddEntry(This->cache, name, entry); } break; case VT_DISPATCH: { xmlDocPtr doc = NULL; cache_entry* entry; SCHEMA_TYPE type; IXMLDOMNode* domnode = NULL; IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IXMLDOMNode, (void**)&domnode); if (domnode) doc = xmlNodePtr_from_domnode(domnode, XML_DOCUMENT_NODE)->doc; if (!doc) { IXMLDOMNode_Release(domnode); heap_free(name); return E_INVALIDARG; } type = schema_type_from_xmlDocPtr(doc); if (type == SCHEMA_TYPE_XSD) { entry = cache_entry_from_xsd_doc(doc); } else if (type == SCHEMA_TYPE_XDR) { entry = cache_entry_from_xdr_doc(doc); } else { WARN("invalid schema!\n"); entry = NULL; } IXMLDOMNode_Release(domnode); if (entry) { cache_entry_add_ref(entry); } else { heap_free(name); return E_FAIL; } xmlHashRemoveEntry(This->cache, name, cache_free); xmlHashAddEntry(This->cache, name, entry); } break; default: { heap_free(name); return E_INVALIDARG; } } heap_free(name); return S_OK; }