* Sync with Wine 1.5.26.

svn path=/trunk/; revision=58579
This commit is contained in:
Amine Khaldi 2013-03-22 16:13:43 +00:00
parent f64a5ef35e
commit e8316eb4bf
19 changed files with 848 additions and 366 deletions

View file

@ -606,7 +606,7 @@ static HRESULT WINAPI domattr_put_value(
TRACE("(%p)->(%s)\n", This, debugstr_variant(&value)); TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
return node_put_value(&This->node, &value); return node_put_value_escaped(&This->node, &value);
} }
static const struct IXMLDOMAttributeVtbl domattr_vtbl = static const struct IXMLDOMAttributeVtbl domattr_vtbl =

View file

@ -293,10 +293,9 @@ static HRESULT WINAPI domcdata_insertBefore(
IXMLDOMNode** outOldNode) IXMLDOMNode** outOldNode)
{ {
domcdata *This = impl_from_IXMLDOMCDATASection( iface ); domcdata *This = impl_from_IXMLDOMCDATASection( iface );
TRACE("(%p)->(%p %s %p)\n", This, newNode, debugstr_variant(&refChild), outOldNode);
FIXME("(%p)->(%p %s %p) needs test\n", This, newNode, debugstr_variant(&refChild), outOldNode); if (outOldNode) *outOldNode = NULL;
return E_FAIL;
return node_insert_before(&This->node, newNode, &refChild, outOldNode);
} }
static HRESULT WINAPI domcdata_replaceChild( static HRESULT WINAPI domcdata_replaceChild(
@ -306,10 +305,9 @@ static HRESULT WINAPI domcdata_replaceChild(
IXMLDOMNode** outOldNode) IXMLDOMNode** outOldNode)
{ {
domcdata *This = impl_from_IXMLDOMCDATASection( iface ); domcdata *This = impl_from_IXMLDOMCDATASection( iface );
TRACE("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
FIXME("(%p)->(%p %p %p) needs tests\n", This, newNode, oldNode, outOldNode); if (outOldNode) *outOldNode = NULL;
return E_FAIL;
return node_replace_child(&This->node, newNode, oldNode, outOldNode);
} }
static HRESULT WINAPI domcdata_removeChild( static HRESULT WINAPI domcdata_removeChild(
@ -318,7 +316,8 @@ static HRESULT WINAPI domcdata_removeChild(
{ {
domcdata *This = impl_from_IXMLDOMCDATASection( iface ); domcdata *This = impl_from_IXMLDOMCDATASection( iface );
TRACE("(%p)->(%p %p)\n", This, child, oldChild); TRACE("(%p)->(%p %p)\n", This, child, oldChild);
return node_remove_child(&This->node, child, oldChild); if (oldChild) *oldChild = NULL;
return E_FAIL;
} }
static HRESULT WINAPI domcdata_appendChild( static HRESULT WINAPI domcdata_appendChild(
@ -327,7 +326,8 @@ static HRESULT WINAPI domcdata_appendChild(
{ {
domcdata *This = impl_from_IXMLDOMCDATASection( iface ); domcdata *This = impl_from_IXMLDOMCDATASection( iface );
TRACE("(%p)->(%p %p)\n", This, child, outChild); TRACE("(%p)->(%p %p)\n", This, child, outChild);
return node_append_child(&This->node, child, outChild); if (outChild) *outChild = NULL;
return E_FAIL;
} }
static HRESULT WINAPI domcdata_hasChildNodes( static HRESULT WINAPI domcdata_hasChildNodes(

View file

@ -601,6 +601,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
hres = IUnknown_QueryInterface(This->outer, get_riid_from_tid(data->funcs[n].tid), (void**)&unk); hres = IUnknown_QueryInterface(This->outer, get_riid_from_tid(data->funcs[n].tid), (void**)&unk);
if(FAILED(hres)) { if(FAILED(hres)) {
ERR("Could not get iface: %08x\n", hres); ERR("Could not get iface: %08x\n", hres);
ITypeInfo_Release(ti);
return E_FAIL; return E_FAIL;
} }

View file

@ -135,9 +135,6 @@ struct domdoc
bsc_t *bsc; bsc_t *bsc;
HRESULT error; HRESULT error;
/* IPersistStream */
IStream *stream;
/* IObjectWithSite*/ /* IObjectWithSite*/
IUnknown *site; IUnknown *site;
@ -559,18 +556,27 @@ void xmldoc_init(xmlDocPtr doc, MSXML_VERSION version)
priv_from_xmlDocPtr(doc)->properties = create_properties(version); priv_from_xmlDocPtr(doc)->properties = create_properties(version);
} }
LONG xmldoc_add_ref(xmlDocPtr doc) LONG xmldoc_add_refs(xmlDocPtr doc, LONG refs)
{ {
LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs); LONG ref = InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc)->refs, refs) + refs;
TRACE("(%p)->(%d)\n", doc, ref); TRACE("(%p)->(%d)\n", doc, ref);
return ref; return ref;
} }
LONG xmldoc_release(xmlDocPtr doc) LONG xmldoc_add_ref(xmlDocPtr doc)
{
return xmldoc_add_refs(doc, 1);
}
LONG xmldoc_release_refs(xmlDocPtr doc, LONG refs)
{ {
xmldoc_priv *priv = priv_from_xmlDocPtr(doc); xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
LONG ref = InterlockedDecrement(&priv->refs); LONG ref = InterlockedExchangeAdd(&priv->refs, -refs) - refs;
TRACE("(%p)->(%d)\n", doc, ref); TRACE("(%p)->(%d)\n", doc, ref);
if (ref < 0)
WARN("negative refcount, expect troubles\n");
if (ref == 0) if (ref == 0)
{ {
orphan_entry *orphan, *orphan2; orphan_entry *orphan, *orphan2;
@ -590,6 +596,11 @@ LONG xmldoc_release(xmlDocPtr doc)
return ref; return ref;
} }
LONG xmldoc_release(xmlDocPtr doc)
{
return xmldoc_release_refs(doc, 1);
}
HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node) HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
{ {
xmldoc_priv *priv = priv_from_xmlDocPtr(doc); xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
@ -624,7 +635,7 @@ HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
static inline xmlDocPtr get_doc( domdoc *This ) static inline xmlDocPtr get_doc( domdoc *This )
{ {
return (xmlDocPtr)This->node.node; return This->node.node->doc;
} }
static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml ) static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
@ -721,46 +732,42 @@ static HRESULT WINAPI PersistStreamInit_IsDirty(
return S_FALSE; return S_FALSE;
} }
static HRESULT WINAPI PersistStreamInit_Load( static HRESULT domdoc_load_from_stream(domdoc *doc, ISequentialStream *stream)
IPersistStreamInit *iface, LPSTREAM pStm)
{ {
domdoc *This = impl_from_IPersistStreamInit(iface);
HRESULT hr;
HGLOBAL hglobal;
DWORD read, written, len; DWORD read, written, len;
BYTE buf[4096];
char *ptr;
xmlDocPtr xmldoc = NULL; xmlDocPtr xmldoc = NULL;
IStream *hstream;
HGLOBAL hglobal;
BYTE buf[4096];
HRESULT hr;
char *ptr;
TRACE("(%p)->(%p)\n", This, pStm); hstream = NULL;
hr = CreateStreamOnHGlobal(NULL, TRUE, &hstream);
if (!pStm)
return E_INVALIDARG;
hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
do do
{ {
IStream_Read(pStm, buf, sizeof(buf), &read); ISequentialStream_Read(stream, buf, sizeof(buf), &read);
hr = IStream_Write(This->stream, buf, read, &written); hr = IStream_Write(hstream, buf, read, &written);
} while(SUCCEEDED(hr) && written != 0 && read != 0); } while(SUCCEEDED(hr) && written != 0 && read != 0);
if (FAILED(hr)) if (FAILED(hr))
{ {
ERR("Failed to copy stream\n"); ERR("failed to copy stream 0x%08x\n", hr);
IStream_Release(hstream);
return hr; return hr;
} }
hr = GetHGlobalFromStream(This->stream, &hglobal); hr = GetHGlobalFromStream(hstream, &hglobal);
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
len = GlobalSize(hglobal); len = GlobalSize(hglobal);
ptr = GlobalLock(hglobal); ptr = GlobalLock(hglobal);
if (len != 0) if (len)
xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE); xmldoc = doparse(doc, ptr, len, XML_CHAR_ENCODING_NONE);
GlobalUnlock(hglobal); GlobalUnlock(hglobal);
if (!xmldoc) if (!xmldoc)
@ -771,7 +778,19 @@ static HRESULT WINAPI PersistStreamInit_Load(
xmldoc->_private = create_priv(); xmldoc->_private = create_priv();
return attach_xmldoc(This, xmldoc); return attach_xmldoc(doc, xmldoc);
}
static HRESULT WINAPI PersistStreamInit_Load(IPersistStreamInit *iface, IStream *stream)
{
domdoc *This = impl_from_IPersistStreamInit(iface);
TRACE("(%p)->(%p)\n", This, stream);
if (!stream)
return E_INVALIDARG;
return domdoc_load_from_stream(This, (ISequentialStream*)stream);
} }
static HRESULT WINAPI PersistStreamInit_Save( static HRESULT WINAPI PersistStreamInit_Save(
@ -801,7 +820,7 @@ static HRESULT WINAPI PersistStreamInit_GetSizeMax(
IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize) IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
{ {
domdoc *This = impl_from_IPersistStreamInit(iface); domdoc *This = impl_from_IPersistStreamInit(iface);
TRACE("(%p)->(%p): stub!\n", This, pcbSize); TRACE("(%p)->(%p)\n", This, pcbSize);
return E_NOTIMPL; return E_NOTIMPL;
} }
@ -914,8 +933,6 @@ static ULONG WINAPI domdoc_Release( IXMLDOMDocument3 *iface )
if (This->site) if (This->site)
IUnknown_Release( This->site ); IUnknown_Release( This->site );
destroy_xmlnode(&This->node); destroy_xmlnode(&This->node);
if (This->stream)
IStream_Release(This->stream);
for (eid = 0; eid < EVENTID_LAST; eid++) for (eid = 0; eid < EVENTID_LAST; eid++)
if (This->events[eid]) IDispatch_Release(This->events[eid]); if (This->events[eid]) IDispatch_Release(This->events[eid]);
@ -1115,12 +1132,26 @@ static HRESULT WINAPI domdoc_insertBefore(
IXMLDOMNode** outNewChild ) IXMLDOMNode** outNewChild )
{ {
domdoc *This = impl_from_IXMLDOMDocument3( iface ); domdoc *This = impl_from_IXMLDOMDocument3( iface );
DOMNodeType type;
HRESULT hr;
TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), outNewChild); TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), outNewChild);
hr = IXMLDOMNode_get_nodeType(newChild, &type);
if (hr != S_OK) return hr;
TRACE("new node type %d\n", type);
switch (type)
{
case NODE_ATTRIBUTE:
case NODE_DOCUMENT:
case NODE_CDATA_SECTION:
if (outNewChild) *outNewChild = NULL;
return E_FAIL;
default:
return node_insert_before(&This->node, newChild, &refChild, outNewChild); return node_insert_before(&This->node, newChild, &refChild, outNewChild);
} }
}
static HRESULT WINAPI domdoc_replaceChild( static HRESULT WINAPI domdoc_replaceChild(
IXMLDOMDocument3 *iface, IXMLDOMDocument3 *iface,
@ -1510,7 +1541,9 @@ static HRESULT WINAPI domdoc_put_documentElement(
domdoc *This = impl_from_IXMLDOMDocument3( iface ); domdoc *This = impl_from_IXMLDOMDocument3( iface );
IXMLDOMNode *elementNode; IXMLDOMNode *elementNode;
xmlNodePtr oldRoot; xmlNodePtr oldRoot;
xmlDocPtr old_doc;
xmlnode *xmlNode; xmlnode *xmlNode;
int refcount = 0;
HRESULT hr; HRESULT hr;
TRACE("(%p)->(%p)\n", This, DOMElement); TRACE("(%p)->(%p)\n", This, DOMElement);
@ -1526,7 +1559,14 @@ static HRESULT WINAPI domdoc_put_documentElement(
if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK) if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node); WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
old_doc = xmlNode->node->doc;
if (old_doc != get_doc(This))
refcount = xmlnode_get_inst_cnt(xmlNode);
/* old root is still orphaned by its document, update refcount from new root */
if (refcount) xmldoc_add_refs(get_doc(This), refcount);
oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node); oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
if (refcount) xmldoc_release_refs(old_doc, refcount);
IXMLDOMNode_Release( elementNode ); IXMLDOMNode_Release( elementNode );
if(oldRoot) if(oldRoot)
@ -2029,8 +2069,6 @@ static HRESULT WINAPI domdoc_load(
domdoc *This = impl_from_IXMLDOMDocument3( iface ); domdoc *This = impl_from_IXMLDOMDocument3( iface );
LPWSTR filename = NULL; LPWSTR filename = NULL;
HRESULT hr = S_FALSE; HRESULT hr = S_FALSE;
IXMLDOMDocument3 *pNewDoc = NULL;
IStream *pStream = NULL;
xmlDocPtr xmldoc; xmlDocPtr xmldoc;
TRACE("(%p)->(%s)\n", This, debugstr_variant(&source)); TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
@ -2096,13 +2134,18 @@ static HRESULT WINAPI domdoc_load(
} }
break; break;
case VT_UNKNOWN: case VT_UNKNOWN:
{
ISequentialStream *stream = NULL;
IXMLDOMDocument3 *newdoc = NULL;
if (!V_UNKNOWN(&source)) return E_INVALIDARG; if (!V_UNKNOWN(&source)) return E_INVALIDARG;
hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&newdoc);
if(hr == S_OK) if(hr == S_OK)
{ {
if(pNewDoc) if(newdoc)
{ {
domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc ); domdoc *newDoc = impl_from_IXMLDOMDocument3( newdoc );
xmldoc = xmlCopyDoc(get_doc(newDoc), 1); xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
xmldoc->_private = create_priv(); xmldoc->_private = create_priv();
@ -2114,38 +2157,23 @@ static HRESULT WINAPI domdoc_load(
return hr; return hr;
} }
} }
hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&pStream);
if(hr == S_OK)
{
IPersistStream *pDocStream;
hr = IXMLDOMDocument3_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
if(hr == S_OK)
{
hr = IPersistStream_Load(pDocStream, pStream);
IStream_Release(pStream);
if(hr == S_OK)
{
*isSuccessful = VARIANT_TRUE;
TRACE("Using IStream to load Document\n"); hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&stream);
return S_OK; if (FAILED(hr))
} hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_ISequentialStream, (void**)&stream);
else
if (hr == S_OK)
{ {
ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr); hr = domdoc_load_from_stream(This, stream);
} if (hr == S_OK)
} *isSuccessful = VARIANT_TRUE;
else ISequentialStream_Release(stream);
{ return hr;
ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
}
}
else
{
/* ISequentialStream */
FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl);
} }
FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr, V_UNKNOWN(&source)->lpVtbl);
break; break;
}
default: default:
FIXME("VT type not supported (%d)\n", V_VT(&source)); FIXME("VT type not supported (%d)\n", V_VT(&source));
} }
@ -3251,12 +3279,43 @@ static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoi
return S_OK; return S_OK;
} }
static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink, static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *unk_sink,
DWORD *pdwCookie) DWORD *cookie)
{ {
ConnectionPoint *This = impl_from_IConnectionPoint(iface); ConnectionPoint *This = impl_from_IConnectionPoint(iface);
FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie); IUnknown *sink;
return E_NOTIMPL; HRESULT hr;
DWORD i;
TRACE("(%p)->(%p %p)\n", This, unk_sink, cookie);
hr = IUnknown_QueryInterface(unk_sink, This->iid, (void**)&sink);
if(FAILED(hr) && !IsEqualGUID(&IID_IPropertyNotifySink, This->iid))
hr = IUnknown_QueryInterface(unk_sink, &IID_IDispatch, (void**)&sink);
if(FAILED(hr))
return CONNECT_E_CANNOTCONNECT;
if(This->sinks)
{
for (i = 0; i < This->sinks_size; i++)
if (!This->sinks[i].unk)
break;
if (i == This->sinks_size)
This->sinks = heap_realloc(This->sinks,(++This->sinks_size)*sizeof(*This->sinks));
}
else
{
This->sinks = heap_alloc(sizeof(*This->sinks));
This->sinks_size = 1;
i = 0;
}
This->sinks[i].unk = sink;
if (cookie)
*cookie = i+1;
return S_OK;
} }
static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie) static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
@ -3466,7 +3525,6 @@ HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
doc->resolving = 0; doc->resolving = 0;
doc->properties = properties_from_xmlDocPtr(xmldoc); doc->properties = properties_from_xmlDocPtr(xmldoc);
doc->error = S_OK; doc->error = S_OK;
doc->stream = NULL;
doc->site = NULL; doc->site = NULL;
doc->safeopt = 0; doc->safeopt = 0;
doc->bsc = NULL; doc->bsc = NULL;

View file

@ -304,13 +304,29 @@ static HRESULT WINAPI domelem_get_attributes(
static HRESULT WINAPI domelem_insertBefore( static HRESULT WINAPI domelem_insertBefore(
IXMLDOMElement *iface, IXMLDOMElement *iface,
IXMLDOMNode* newNode, VARIANT refChild, IXMLDOMNode* newNode, VARIANT refChild,
IXMLDOMNode** outOldNode) IXMLDOMNode** old_node)
{ {
domelem *This = impl_from_IXMLDOMElement( iface ); domelem *This = impl_from_IXMLDOMElement( iface );
DOMNodeType type;
HRESULT hr;
TRACE("(%p)->(%p %s %p)\n", This, newNode, debugstr_variant(&refChild), outOldNode); TRACE("(%p)->(%p %s %p)\n", This, newNode, debugstr_variant(&refChild), old_node);
return node_insert_before(&This->node, newNode, &refChild, outOldNode); hr = IXMLDOMNode_get_nodeType(newNode, &type);
if (hr != S_OK) return hr;
TRACE("new node type %d\n", type);
switch (type)
{
case NODE_DOCUMENT:
case NODE_DOCUMENT_TYPE:
case NODE_ENTITY:
case NODE_NOTATION:
if (old_node) *old_node = NULL;
return E_FAIL;
default:
return node_insert_before(&This->node, newNode, &refChild, old_node);
}
} }
static HRESULT WINAPI domelem_replaceChild( static HRESULT WINAPI domelem_replaceChild(
@ -739,7 +755,7 @@ static HRESULT encode_base64(const BYTE *buf, int len, BSTR *ret)
{ {
static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const BYTE *d = buf; const BYTE *d = buf;
int bytes, pad_bytes, div, i; int bytes, pad_bytes, div;
DWORD needed; DWORD needed;
WCHAR *ptr; WCHAR *ptr;
@ -756,7 +772,6 @@ static HRESULT encode_base64(const BYTE *buf, int len, BSTR *ret)
div = len / 3; div = len / 3;
ptr = *ret; ptr = *ret;
i = 0;
while (div > 0) while (div > 0)
{ {
/* first char is the first 6 bits of the first byte*/ /* first char is the first 6 bits of the first byte*/
@ -769,7 +784,6 @@ static HRESULT encode_base64(const BYTE *buf, int len, BSTR *ret)
*ptr++ = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)]; *ptr++ = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)];
/* fourth char is the remaining 6 bits of the third byte */ /* fourth char is the remaining 6 bits of the third byte */
*ptr++ = b64[ d[2] & 0x3f]; *ptr++ = b64[ d[2] & 0x3f];
i += 4;
d += 3; d += 3;
div--; div--;
} }
@ -1232,8 +1246,7 @@ static HRESULT WINAPI domelem_setAttribute(
domelem *This = impl_from_IXMLDOMElement( iface ); domelem *This = impl_from_IXMLDOMElement( iface );
xmlChar *xml_name, *xml_value, *local, *prefix; xmlChar *xml_name, *xml_value, *local, *prefix;
xmlNodePtr element; xmlNodePtr element;
HRESULT hr; HRESULT hr = S_OK;
VARIANT var;
TRACE("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_variant(&value)); TRACE("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_variant(&value));
@ -1241,6 +1254,10 @@ static HRESULT WINAPI domelem_setAttribute(
if ( !element ) if ( !element )
return E_FAIL; return E_FAIL;
if (V_VT(&value) != VT_BSTR)
{
VARIANT var;
VariantInit(&var); VariantInit(&var);
hr = VariantChangeType(&var, &value, 0, VT_BSTR); hr = VariantChangeType(&var, &value, 0, VT_BSTR);
if (hr != S_OK) if (hr != S_OK)
@ -1249,8 +1266,13 @@ static HRESULT WINAPI domelem_setAttribute(
return hr; return hr;
} }
xml_name = xmlchar_from_wchar( name );
xml_value = xmlchar_from_wchar(V_BSTR(&var)); xml_value = xmlchar_from_wchar(V_BSTR(&var));
VariantClear(&var);
}
else
xml_value = xmlchar_from_wchar(V_BSTR(&value));
xml_name = xmlchar_from_wchar( name );
if ((local = xmlSplitQName2(xml_name, &prefix))) if ((local = xmlSplitQName2(xml_name, &prefix)))
{ {
@ -1273,7 +1295,6 @@ static HRESULT WINAPI domelem_setAttribute(
heap_free(xml_value); heap_free(xml_value);
heap_free(xml_name); heap_free(xml_name);
VariantClear(&var);
return hr; return hr;
} }

View file

@ -101,7 +101,7 @@ static const struct clsid_version_t clsid_versions_table[] =
static MSXML_VERSION get_msxml_version(const GUID *clsid) static MSXML_VERSION get_msxml_version(const GUID *clsid)
{ {
int i; unsigned int i;
for (i = 0; i < sizeof(clsid_versions_table)/sizeof(struct clsid_version_t); i++) for (i = 0; i < sizeof(clsid_versions_table)/sizeof(struct clsid_version_t); i++)
if (IsEqualGUID(clsid, clsid_versions_table[i].clsid)) if (IsEqualGUID(clsid, clsid_versions_table[i].clsid))

View file

@ -85,8 +85,8 @@ typedef struct
/* request */ /* request */
BINDVERB verb; BINDVERB verb;
BSTR custom; BSTR custom;
BSTR siteurl; IUri *uri;
BSTR url; IUri *base_uri;
BOOL async; BOOL async;
struct list reqheaders; struct list reqheaders;
/* cached resulting custom request headers string length in WCHARs */ /* cached resulting custom request headers string length in WCHARs */
@ -144,9 +144,17 @@ static inline serverhttp *impl_from_IServerXMLHTTPRequest(IServerXMLHTTPRequest
static void httprequest_setreadystate(httprequest *This, READYSTATE state) static void httprequest_setreadystate(httprequest *This, READYSTATE state)
{ {
READYSTATE last = This->state; READYSTATE last = This->state;
static const char* readystates[] = {
"READYSTATE_UNINITIALIZED",
"READYSTATE_LOADING",
"READYSTATE_LOADED",
"READYSTATE_INTERACTIVE",
"READYSTATE_COMPLETE"};
This->state = state; This->state = state;
TRACE("state %s\n", readystates[state]);
if (This->sink && last != state) if (This->sink && last != state)
{ {
DISPPARAMS params; DISPPARAMS params;
@ -209,6 +217,7 @@ static void BindStatusCallback_Detach(BindStatusCallback *bsc)
if (bsc) if (bsc)
{ {
if (bsc->binding) IBinding_Abort(bsc->binding); if (bsc->binding) IBinding_Abort(bsc->binding);
bsc->request->bsc = NULL;
bsc->request = NULL; bsc->request = NULL;
IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface); IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
} }
@ -343,7 +352,11 @@ static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *ifac
} }
if (hr == S_OK) if (hr == S_OK)
{
BindStatusCallback_Detach(This->request->bsc);
This->request->bsc = This;
httprequest_setreadystate(This->request, READYSTATE_COMPLETE); httprequest_setreadystate(This->request, READYSTATE_COMPLETE);
}
return S_OK; return S_OK;
} }
@ -688,23 +701,28 @@ static HRESULT BindStatusCallback_create(httprequest* This, BindStatusCallback *
case VT_ARRAY|VT_UI1: case VT_ARRAY|VT_UI1:
{ {
sa = V_ARRAY(body); sa = V_ARRAY(body);
if ((hr = SafeArrayAccessData(sa, (void **)&ptr)) != S_OK) return hr; if ((hr = SafeArrayAccessData(sa, (void **)&ptr)) != S_OK)
{
heap_free(bsc);
return hr;
}
if ((hr = SafeArrayGetUBound(sa, 1, &size) != S_OK)) if ((hr = SafeArrayGetUBound(sa, 1, &size) != S_OK))
{ {
SafeArrayUnaccessData(sa); SafeArrayUnaccessData(sa);
heap_free(bsc);
return hr; return hr;
} }
size++; size++;
break; break;
} }
default:
FIXME("unsupported body data type %d\n", V_VT(body));
/* fall through */
case VT_EMPTY: case VT_EMPTY:
case VT_ERROR: case VT_ERROR:
ptr = NULL; ptr = NULL;
size = 0; size = 0;
break; break;
default:
FIXME("unsupported body data type %d\n", V_VT(body));
break;
} }
bsc->body = GlobalAlloc(GMEM_FIXED, size); bsc->body = GlobalAlloc(GMEM_FIXED, size);
@ -734,7 +752,7 @@ static HRESULT BindStatusCallback_create(httprequest* This, BindStatusCallback *
{ {
IMoniker *moniker; IMoniker *moniker;
hr = CreateURLMoniker(NULL, This->url, &moniker); hr = CreateURLMonikerEx2(NULL, This->uri, &moniker, URL_MK_UNIFORM);
if (hr == S_OK) if (hr == S_OK)
{ {
IStream *stream; IStream *stream;
@ -756,6 +774,53 @@ static HRESULT BindStatusCallback_create(httprequest* This, BindStatusCallback *
return hr; return hr;
} }
static HRESULT verify_uri(httprequest *This, IUri *uri)
{
DWORD scheme, base_scheme;
BSTR host, base_host;
HRESULT hr;
if(!(This->safeopt & INTERFACESAFE_FOR_UNTRUSTED_DATA))
return S_OK;
if(!This->base_uri)
return E_ACCESSDENIED;
hr = IUri_GetScheme(uri, &scheme);
if(FAILED(hr))
return hr;
hr = IUri_GetScheme(This->base_uri, &base_scheme);
if(FAILED(hr))
return hr;
if(scheme != base_scheme) {
WARN("Schemes don't match\n");
return E_ACCESSDENIED;
}
if(scheme == INTERNET_SCHEME_UNKNOWN) {
FIXME("Unknown scheme\n");
return E_ACCESSDENIED;
}
hr = IUri_GetHost(uri, &host);
if(FAILED(hr))
return hr;
hr = IUri_GetHost(This->base_uri, &base_host);
if(SUCCEEDED(hr)) {
if(strcmpiW(host, base_host)) {
WARN("Hosts don't match\n");
hr = E_ACCESSDENIED;
}
SysFreeString(base_host);
}
SysFreeString(host);
return hr;
}
static HRESULT httprequest_open(httprequest *This, BSTR method, BSTR url, static HRESULT httprequest_open(httprequest *This, BSTR method, BSTR url,
VARIANT async, VARIANT user, VARIANT password) VARIANT async, VARIANT user, VARIANT password)
{ {
@ -765,15 +830,20 @@ static HRESULT httprequest_open(httprequest *This, BSTR method, BSTR url,
static const WCHAR MethodDeleteW[] = {'D','E','L','E','T','E',0}; static const WCHAR MethodDeleteW[] = {'D','E','L','E','T','E',0};
static const WCHAR MethodPropFindW[] = {'P','R','O','P','F','I','N','D',0}; static const WCHAR MethodPropFindW[] = {'P','R','O','P','F','I','N','D',0};
VARIANT str, is_async; VARIANT str, is_async;
IUri *uri;
HRESULT hr; HRESULT hr;
if (!method || !url) return E_INVALIDARG; if (!method || !url) return E_INVALIDARG;
/* free previously set data */ /* free previously set data */
SysFreeString(This->url); if(This->uri) {
IUri_Release(This->uri);
This->uri = NULL;
}
SysFreeString(This->user); SysFreeString(This->user);
SysFreeString(This->password); SysFreeString(This->password);
This->url = This->user = This->password = NULL; This->user = This->password = NULL;
if (!strcmpiW(method, MethodGetW)) if (!strcmpiW(method, MethodGetW))
{ {
@ -800,22 +870,22 @@ static HRESULT httprequest_open(httprequest *This, BSTR method, BSTR url,
return E_FAIL; return E_FAIL;
} }
/* try to combine with site url */ if(This->base_uri)
if (This->siteurl && PathIsRelativeW(url)) hr = CoInternetCombineUrlEx(This->base_uri, url, 0, &uri, 0);
{
DWORD len = INTERNET_MAX_URL_LENGTH;
WCHAR *fullW = heap_alloc(len*sizeof(WCHAR));
hr = UrlCombineW(This->siteurl, url, fullW, &len, 0);
if (hr == S_OK)
{
TRACE("combined url %s\n", debugstr_w(fullW));
This->url = SysAllocString(fullW);
}
heap_free(fullW);
}
else else
This->url = SysAllocString(url); hr = CreateUri(url, 0, 0, &uri);
if(FAILED(hr)) {
WARN("Could not create IUri object: %08x\n", hr);
return hr;
}
hr = verify_uri(This, uri);
if(FAILED(hr)) {
IUri_Release(uri);
return hr;
}
This->uri = uri;
VariantInit(&is_async); VariantInit(&is_async);
hr = VariantChangeType(&is_async, &async, 0, VT_BOOL); hr = VariantChangeType(&is_async, &async, 0, VT_BOOL);
@ -881,7 +951,8 @@ static HRESULT httprequest_getResponseHeader(httprequest *This, BSTR header, BST
{ {
struct httpheader *entry; struct httpheader *entry;
if (!header || !value) return E_INVALIDARG; if (!header) return E_INVALIDARG;
if (!value) return E_POINTER;
if (This->raw_respheaders && list_empty(&This->respheaders)) if (This->raw_respheaders && list_empty(&This->respheaders))
{ {
@ -915,7 +986,7 @@ static HRESULT httprequest_getResponseHeader(httprequest *This, BSTR header, BST
static HRESULT httprequest_getAllResponseHeaders(httprequest *This, BSTR *respheaders) static HRESULT httprequest_getAllResponseHeaders(httprequest *This, BSTR *respheaders)
{ {
if (!respheaders) return E_INVALIDARG; if (!respheaders) return E_POINTER;
*respheaders = SysAllocString(This->raw_respheaders); *respheaders = SysAllocString(This->raw_respheaders);
@ -930,10 +1001,9 @@ static HRESULT httprequest_send(httprequest *This, VARIANT body)
if (This->state != READYSTATE_LOADING) return E_FAIL; if (This->state != READYSTATE_LOADING) return E_FAIL;
hr = BindStatusCallback_create(This, &bsc, &body); hr = BindStatusCallback_create(This, &bsc, &body);
if (FAILED(hr)) return hr; if (FAILED(hr))
/* success path to detach it is OnStopBinding call */
BindStatusCallback_Detach(This->bsc); BindStatusCallback_Detach(bsc);
This->bsc = bsc;
return hr; return hr;
} }
@ -941,7 +1011,6 @@ static HRESULT httprequest_send(httprequest *This, VARIANT body)
static HRESULT httprequest_abort(httprequest *This) static HRESULT httprequest_abort(httprequest *This)
{ {
BindStatusCallback_Detach(This->bsc); BindStatusCallback_Detach(This->bsc);
This->bsc = NULL;
httprequest_setreadystate(This, READYSTATE_UNINITIALIZED); httprequest_setreadystate(This, READYSTATE_UNINITIALIZED);
@ -950,17 +1019,16 @@ static HRESULT httprequest_abort(httprequest *This)
static HRESULT httprequest_get_status(httprequest *This, LONG *status) static HRESULT httprequest_get_status(httprequest *This, LONG *status)
{ {
if (!status) return E_INVALIDARG; if (!status) return E_POINTER;
if (This->state != READYSTATE_COMPLETE) return E_FAIL;
*status = This->status; *status = This->status;
return S_OK; return This->state == READYSTATE_COMPLETE ? S_OK : E_FAIL;
} }
static HRESULT httprequest_get_statusText(httprequest *This, BSTR *status) static HRESULT httprequest_get_statusText(httprequest *This, BSTR *status)
{ {
if (!status) return E_INVALIDARG; if (!status) return E_POINTER;
if (This->state != READYSTATE_COMPLETE) return E_FAIL; if (This->state != READYSTATE_COMPLETE) return E_FAIL;
*status = SysAllocString(This->status_text); *status = SysAllocString(This->status_text);
@ -973,7 +1041,7 @@ static HRESULT httprequest_get_responseText(httprequest *This, BSTR *body)
HGLOBAL hglobal; HGLOBAL hglobal;
HRESULT hr; HRESULT hr;
if (!body) return E_INVALIDARG; if (!body) return E_POINTER;
if (This->state != READYSTATE_COMPLETE) return E_FAIL; if (This->state != READYSTATE_COMPLETE) return E_FAIL;
hr = GetHGlobalFromStream(This->bsc->stream, &hglobal); hr = GetHGlobalFromStream(This->bsc->stream, &hglobal);
@ -1119,7 +1187,7 @@ static HRESULT httprequest_get_responseStream(httprequest *This, VARIANT *body)
static HRESULT httprequest_get_readyState(httprequest *This, LONG *state) static HRESULT httprequest_get_readyState(httprequest *This, LONG *state)
{ {
if (!state) return E_INVALIDARG; if (!state) return E_POINTER;
*state = This->state; *state = This->state;
return S_OK; return S_OK;
@ -1139,10 +1207,12 @@ static void httprequest_release(httprequest *This)
if (This->site) if (This->site)
IUnknown_Release( This->site ); IUnknown_Release( This->site );
if (This->uri)
IUri_Release(This->uri);
if (This->base_uri)
IUri_Release(This->base_uri);
SysFreeString(This->custom); SysFreeString(This->custom);
SysFreeString(This->siteurl);
SysFreeString(This->url);
SysFreeString(This->user); SysFreeString(This->user);
SysFreeString(This->password); SysFreeString(This->password);
@ -1442,37 +1512,55 @@ static HRESULT WINAPI httprequest_ObjectWithSite_GetSite( IObjectWithSite *iface
return IUnknown_QueryInterface( This->site, iid, ppvSite ); return IUnknown_QueryInterface( This->site, iid, ppvSite );
} }
static void get_base_uri(httprequest *This)
{
IServiceProvider *provider;
IHTMLDocument2 *doc;
IUri *uri;
BSTR url;
HRESULT hr;
hr = IUnknown_QueryInterface(This->site, &IID_IServiceProvider, (void**)&provider);
if(FAILED(hr))
return;
hr = IServiceProvider_QueryService(provider, &SID_SContainerDispatch, &IID_IHTMLDocument2, (void**)&doc);
IServiceProvider_Release(provider);
if(FAILED(hr))
return;
hr = IHTMLDocument2_get_URL(doc, &url);
IHTMLDocument2_Release(doc);
if(FAILED(hr) || !url || !*url)
return;
TRACE("host url %s\n", debugstr_w(url));
hr = CreateUri(url, 0, 0, &uri);
SysFreeString(url);
if(FAILED(hr))
return;
This->base_uri = uri;
}
static HRESULT WINAPI httprequest_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk ) static HRESULT WINAPI httprequest_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
{ {
httprequest *This = impl_from_IObjectWithSite(iface); httprequest *This = impl_from_IObjectWithSite(iface);
IServiceProvider *provider;
HRESULT hr;
TRACE("(%p)->(%p)\n", iface, punk); TRACE("(%p)->(%p)\n", This, punk);
if (punk)
IUnknown_AddRef( punk );
if(This->site) if(This->site)
IUnknown_Release( This->site ); IUnknown_Release( This->site );
if(This->base_uri)
IUri_Release(This->base_uri);
This->site = punk; This->site = punk;
hr = IUnknown_QueryInterface(This->site, &IID_IServiceProvider, (void**)&provider); if (punk)
if (hr == S_OK)
{ {
IHTMLDocument2 *doc; IUnknown_AddRef( punk );
get_base_uri(This);
hr = IServiceProvider_QueryService(provider, &SID_SContainerDispatch, &IID_IHTMLDocument2, (void**)&doc);
if (hr == S_OK)
{
SysFreeString(This->siteurl);
hr = IHTMLDocument2_get_URL(doc, &This->siteurl);
IHTMLDocument2_Release(doc);
TRACE("host url %s, 0x%08x\n", debugstr_w(This->siteurl), hr);
}
IServiceProvider_Release(provider);
} }
return S_OK; return S_OK;
@ -1826,7 +1914,8 @@ static void init_httprequest(httprequest *req)
req->async = FALSE; req->async = FALSE;
req->verb = -1; req->verb = -1;
req->custom = NULL; req->custom = NULL;
req->url = req->siteurl = req->user = req->password = NULL; req->uri = req->base_uri = NULL;
req->user = req->password = NULL;
req->state = READYSTATE_UNINITIALIZED; req->state = READYSTATE_UNINITIALIZED;
req->sink = NULL; req->sink = NULL;

View file

@ -276,6 +276,8 @@ const char *debugstr_variant(const VARIANT *v)
return wine_dbg_sprintf("{VT_I2: %d}", V_I2(v)); return wine_dbg_sprintf("{VT_I2: %d}", V_I2(v));
case VT_I4: case VT_I4:
return wine_dbg_sprintf("{VT_I4: %d}", V_I4(v)); return wine_dbg_sprintf("{VT_I4: %d}", V_I4(v));
case VT_INT:
return wine_dbg_sprintf("{VT_INT: %d}", V_INT(v));
case VT_R8: case VT_R8:
return wine_dbg_sprintf("{VT_R8: %lf}", V_R8(v)); return wine_dbg_sprintf("{VT_R8: %lf}", V_R8(v));
case VT_BSTR: case VT_BSTR:

View file

@ -194,6 +194,7 @@ static inline LPWSTR heap_strdupW(LPCWSTR str)
size = (strlenW(str)+1)*sizeof(WCHAR); size = (strlenW(str)+1)*sizeof(WCHAR);
ret = heap_alloc(size); ret = heap_alloc(size);
if(ret)
memcpy(ret, str, size); memcpy(ret, str, size);
} }
@ -291,6 +292,9 @@ extern xmlChar *xmlChar_from_wchar( LPCWSTR str ) DECLSPEC_HIDDEN;
extern void xmldoc_init( xmlDocPtr doc, MSXML_VERSION version ) DECLSPEC_HIDDEN; extern void xmldoc_init( xmlDocPtr doc, MSXML_VERSION version ) DECLSPEC_HIDDEN;
extern LONG xmldoc_add_ref( xmlDocPtr doc ) DECLSPEC_HIDDEN; extern LONG xmldoc_add_ref( xmlDocPtr doc ) DECLSPEC_HIDDEN;
extern LONG xmldoc_release( xmlDocPtr doc ) DECLSPEC_HIDDEN; extern LONG xmldoc_release( xmlDocPtr doc ) DECLSPEC_HIDDEN;
extern LONG xmldoc_add_refs( xmlDocPtr doc, LONG refs ) DECLSPEC_HIDDEN;
extern LONG xmldoc_release_refs ( xmlDocPtr doc, LONG refs ) DECLSPEC_HIDDEN;
extern int xmlnode_get_inst_cnt( xmlnode *node ) DECLSPEC_HIDDEN;
extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDDEN; extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDDEN;
extern HRESULT xmldoc_remove_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDDEN; extern HRESULT xmldoc_remove_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDDEN;
extern void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node) DECLSPEC_HIDDEN; extern void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node) DECLSPEC_HIDDEN;
@ -404,6 +408,21 @@ static inline xmlChar *xmlchar_from_wchar( const WCHAR *str )
return xmlchar_from_wcharn(str, -1); return xmlchar_from_wcharn(str, -1);
} }
static inline xmlChar *heap_strdupxmlChar(const xmlChar *str)
{
xmlChar *ret = NULL;
if(str) {
DWORD size;
size = (xmlStrlen(str)+1)*sizeof(xmlChar);
ret = heap_alloc(size);
memcpy(ret, str, size);
}
return ret;
}
#endif #endif
static inline HRESULT return_bstr(const WCHAR *value, BSTR *p) static inline HRESULT return_bstr(const WCHAR *value, BSTR *p)

View file

@ -291,7 +291,9 @@ static HRESULT alloc_output_buffer(xml_encoding encoding, output_buffer **buffer
return hr; return hr;
} }
if (ret->code_page == CP_UTF8) { /* currently we always create a default output buffer that is UTF-16 only,
but it's possible to allocate with specific encoding too */
if (encoding != XmlEncoding_UTF16) {
hr = init_encoded_buffer(&ret->encoded); hr = init_encoded_buffer(&ret->encoded);
if (hr != S_OK) { if (hr != S_OK) {
free_encoded_buffer(&ret->utf16); free_encoded_buffer(&ret->utf16);

View file

@ -285,9 +285,12 @@ static HRESULT node_set_content_escaped(xmlnode *This, LPCWSTR value)
HRESULT node_put_value(xmlnode *This, VARIANT *value) HRESULT node_put_value(xmlnode *This, VARIANT *value)
{ {
VARIANT string_value;
HRESULT hr; HRESULT hr;
if (V_VT(value) != VT_BSTR)
{
VARIANT string_value;
VariantInit(&string_value); VariantInit(&string_value);
hr = VariantChangeType(&string_value, value, 0, VT_BSTR); hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
if(FAILED(hr)) { if(FAILED(hr)) {
@ -297,15 +300,21 @@ HRESULT node_put_value(xmlnode *This, VARIANT *value)
hr = node_set_content(This, V_BSTR(&string_value)); hr = node_set_content(This, V_BSTR(&string_value));
VariantClear(&string_value); VariantClear(&string_value);
}
else
hr = node_set_content(This, V_BSTR(value));
return hr; return hr;
} }
HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value) HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
{ {
VARIANT string_value;
HRESULT hr; HRESULT hr;
if (V_VT(value) != VT_BSTR)
{
VARIANT string_value;
VariantInit(&string_value); VariantInit(&string_value);
hr = VariantChangeType(&string_value, value, 0, VT_BSTR); hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
if(FAILED(hr)) { if(FAILED(hr)) {
@ -315,6 +324,9 @@ HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
hr = node_set_content_escaped(This, V_BSTR(&string_value)); hr = node_set_content_escaped(This, V_BSTR(&string_value));
VariantClear(&string_value); VariantClear(&string_value);
}
else
hr = node_set_content_escaped(This, V_BSTR(value));
return hr; return hr;
} }
@ -377,11 +389,45 @@ HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
return get_node(This, "next", This->node->next, ret); return get_node(This, "next", This->node->next, ret);
} }
static int node_get_inst_cnt(xmlNodePtr node)
{
int ret = *(LONG *)&node->_private;
xmlNodePtr child;
/* add attribute counts */
if (node->type == XML_ELEMENT_NODE)
{
xmlAttrPtr prop = node->properties;
while (prop)
{
ret += node_get_inst_cnt((xmlNodePtr)prop);
prop = prop->next;
}
}
/* add children counts */
child = node->children;
while (child)
{
ret += node_get_inst_cnt(child);
child = child->next;
}
return ret;
}
int xmlnode_get_inst_cnt(xmlnode *node)
{
return node_get_inst_cnt(node->node);
}
HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child, HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
IXMLDOMNode **ret) IXMLDOMNode **ret)
{ {
IXMLDOMNode *before = NULL; IXMLDOMNode *before = NULL;
xmlnode *node_obj; xmlnode *node_obj;
int refcount = 0;
xmlDocPtr doc; xmlDocPtr doc;
HRESULT hr; HRESULT hr;
@ -417,6 +463,8 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
if(xmldoc_remove_orphan(node_obj->node->doc, node_obj->node) != S_OK) if(xmldoc_remove_orphan(node_obj->node->doc, node_obj->node) != S_OK)
WARN("%p is not an orphan of %p\n", node_obj->node, node_obj->node->doc); WARN("%p is not an orphan of %p\n", node_obj->node, node_obj->node->doc);
refcount = xmlnode_get_inst_cnt(node_obj);
if(before) if(before)
{ {
xmlnode *before_node_obj = get_node_obj(before); xmlnode *before_node_obj = get_node_obj(before);
@ -429,10 +477,16 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
hr = IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL); hr = IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
if (hr == S_OK) xmldoc_remove_orphan(node_obj->node->doc, node_obj->node); if (hr == S_OK) xmldoc_remove_orphan(node_obj->node->doc, node_obj->node);
} }
doc = node_obj->node->doc; doc = node_obj->node->doc;
xmldoc_add_ref(before_node_obj->node->doc);
/* refs count including subtree */
if (doc != before_node_obj->node->doc)
refcount = xmlnode_get_inst_cnt(node_obj);
if (refcount) xmldoc_add_refs(before_node_obj->node->doc, refcount);
xmlAddPrevSibling(before_node_obj->node, node_obj->node); xmlAddPrevSibling(before_node_obj->node, node_obj->node);
xmldoc_release(doc); if (refcount) xmldoc_release_refs(doc, refcount);
node_obj->parent = This->parent; node_obj->parent = This->parent;
} }
else else
@ -444,11 +498,15 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
if (hr == S_OK) xmldoc_remove_orphan(node_obj->node->doc, node_obj->node); if (hr == S_OK) xmldoc_remove_orphan(node_obj->node->doc, node_obj->node);
} }
doc = node_obj->node->doc; doc = node_obj->node->doc;
xmldoc_add_ref(This->node->doc);
if (doc != This->node->doc)
refcount = xmlnode_get_inst_cnt(node_obj);
if (refcount) xmldoc_add_refs(This->node->doc, refcount);
/* xmlAddChild doesn't unlink node from previous parent */ /* xmlAddChild doesn't unlink node from previous parent */
xmlUnlinkNode(node_obj->node); xmlUnlinkNode(node_obj->node);
xmlAddChild(This->node, node_obj->node); xmlAddChild(This->node, node_obj->node);
xmldoc_release(doc); if (refcount) xmldoc_release_refs(doc, refcount);
node_obj->parent = This->iface; node_obj->parent = This->iface;
} }
@ -468,6 +526,7 @@ HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *ol
xmlnode *old_child, *new_child; xmlnode *old_child, *new_child;
xmlDocPtr leaving_doc; xmlDocPtr leaving_doc;
xmlNode *my_ancestor; xmlNode *my_ancestor;
int refcount = 0;
/* Do not believe any documentation telling that newChild == NULL /* Do not believe any documentation telling that newChild == NULL
means removal. It does certainly *not* apply to msxml3! */ means removal. It does certainly *not* apply to msxml3! */
@ -505,9 +564,13 @@ HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *ol
WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc); WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
leaving_doc = new_child->node->doc; leaving_doc = new_child->node->doc;
xmldoc_add_ref(old_child->node->doc);
if (leaving_doc != old_child->node->doc)
refcount = xmlnode_get_inst_cnt(new_child);
if (refcount) xmldoc_add_refs(old_child->node->doc, refcount);
xmlReplaceNode(old_child->node, new_child->node); xmlReplaceNode(old_child->node, new_child->node);
xmldoc_release(leaving_doc); if (refcount) xmldoc_release_refs(leaving_doc, refcount);
new_child->parent = old_child->parent; new_child->parent = old_child->parent;
old_child->parent = NULL; old_child->parent = NULL;
@ -598,7 +661,7 @@ HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
clone = xmlCopyNode(This->node, deep ? 1 : 2); clone = xmlCopyNode(This->node, deep ? 1 : 2);
if (clone) if (clone)
{ {
clone->doc = This->node->doc; xmlSetTreeDoc(clone, This->node->doc);
xmldoc_add_orphan(clone->doc, clone); xmldoc_add_orphan(clone->doc, clone);
node = create_node(clone); node = create_node(clone);
@ -836,6 +899,53 @@ HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BSTR *ret)
return *ret ? S_OK : E_OUTOFMEMORY; return *ret ? S_OK : E_OUTOFMEMORY;
} }
static void htmldtd_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc)
{
xmlDtdPtr cur = doc->intSubset;
xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
xmlOutputBufferWriteString(buf, (const char *)cur->name);
if (cur->ExternalID)
{
xmlOutputBufferWriteString(buf, " PUBLIC ");
xmlBufferWriteQuotedString(buf->buffer, cur->ExternalID);
if (cur->SystemID)
{
xmlOutputBufferWriteString(buf, " ");
xmlBufferWriteQuotedString(buf->buffer, cur->SystemID);
}
}
else if (cur->SystemID)
{
xmlOutputBufferWriteString(buf, " SYSTEM ");
xmlBufferWriteQuotedString(buf->buffer, cur->SystemID);
}
xmlOutputBufferWriteString(buf, ">\n");
}
static void htmldoc_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc)
{
xmlElementType type;
/* force HTML output */
type = doc->type;
doc->type = XML_HTML_DOCUMENT_NODE;
if (doc->intSubset)
htmldtd_dumpcontent(buf, doc);
if (doc->children)
{
xmlNodePtr cur = doc->children;
while (cur)
{
htmlNodeDumpFormatOutput(buf, doc, cur, NULL, 1);
cur = cur->next;
}
}
doc->type = type;
}
HRESULT node_transform_node(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p) HRESULT node_transform_node(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p)
{ {
#ifdef SONAME_LIBXSLT #ifdef SONAME_LIBXSLT
@ -863,7 +973,7 @@ HRESULT node_transform_node(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *
xmlOutputBufferPtr output = xmlAllocOutputBuffer(NULL); xmlOutputBufferPtr output = xmlAllocOutputBuffer(NULL);
if (output) if (output)
{ {
htmlDocContentDumpOutput(output, result->doc, NULL); htmldoc_dumpcontent(output, result->doc);
content = xmlBufferContent(output->buffer); content = xmlBufferContent(output->buffer);
*p = bstr_from_xmlChar(content); *p = bstr_from_xmlChar(content);
xmlOutputBufferClose(output); xmlOutputBufferClose(output);
@ -973,17 +1083,36 @@ HRESULT node_get_base_name(xmlnode *This, BSTR *name)
return S_OK; return S_OK;
} }
/* _private field holds a number of COM instances spawned from this libxml2 node */
static void xmlnode_add_ref(xmlNodePtr node)
{
if (node->type == XML_DOCUMENT_NODE) return;
InterlockedIncrement((LONG*)&node->_private);
}
static void xmlnode_release(xmlNodePtr node)
{
if (node->type == XML_DOCUMENT_NODE) return;
InterlockedDecrement((LONG*)&node->_private);
}
void destroy_xmlnode(xmlnode *This) void destroy_xmlnode(xmlnode *This)
{ {
if(This->node) if(This->node)
{
xmlnode_release(This->node);
xmldoc_release(This->node->doc); xmldoc_release(This->node->doc);
}
release_dispex(&This->dispex); release_dispex(&This->dispex);
} }
void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data) void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
{ {
if(node) if(node)
{
xmlnode_add_ref(node);
xmldoc_add_ref(node->doc); xmldoc_add_ref(node->doc);
}
This->node = node; This->node = node;
This->iface = node_iface; This->iface = node_iface;

View file

@ -341,18 +341,15 @@ static HRESULT xmlnodelist_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD fl
TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei); TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei);
V_VT(res) = VT_DISPATCH; if (id >= DISPID_DOM_COLLECTION_BASE && id <= DISPID_DOM_COLLECTION_MAX)
V_DISPATCH(res) = NULL; {
if (id < DISPID_DOM_COLLECTION_BASE || id > DISPID_DOM_COLLECTION_MAX)
return DISP_E_UNKNOWNNAME;
switch(flags) switch(flags)
{ {
case INVOKE_PROPERTYGET: case DISPATCH_PROPERTYGET:
{ {
IXMLDOMNode *disp = NULL; IXMLDOMNode *disp = NULL;
V_VT(res) = VT_DISPATCH;
IXMLDOMNodeList_get_item(&This->IXMLDOMNodeList_iface, id - DISPID_DOM_COLLECTION_BASE, &disp); IXMLDOMNodeList_get_item(&This->IXMLDOMNodeList_iface, id - DISPID_DOM_COLLECTION_BASE, &disp);
V_DISPATCH(res) = (IDispatch*)disp; V_DISPATCH(res) = (IDispatch*)disp;
break; break;
@ -363,6 +360,43 @@ static HRESULT xmlnodelist_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD fl
break; break;
} }
} }
}
else if (id == DISPID_VALUE)
{
switch(flags)
{
case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
case DISPATCH_PROPERTYGET:
case DISPATCH_METHOD:
{
IXMLDOMNode *item;
VARIANT index;
HRESULT hr;
if (params->cArgs - params->cNamedArgs != 1) return DISP_E_BADPARAMCOUNT;
VariantInit(&index);
hr = VariantChangeType(&index, params->rgvarg, 0, VT_I4);
if(FAILED(hr))
{
FIXME("failed to convert arg, %s\n", debugstr_variant(params->rgvarg));
return hr;
}
IXMLDOMNodeList_get_item(&This->IXMLDOMNodeList_iface, V_I4(&index), &item);
V_VT(res) = VT_DISPATCH;
V_DISPATCH(res) = (IDispatch*)item;
break;
}
default:
{
FIXME("DISPID_VALUE: unimplemented flags %x\n", flags);
break;
}
}
}
else
return DISP_E_UNKNOWNNAME;
TRACE("ret %p\n", V_DISPATCH(res)); TRACE("ret %p\n", V_DISPATCH(res));

View file

@ -171,12 +171,13 @@ enum saxhandler_type
SAXContentHandler = 0, SAXContentHandler = 0,
SAXDeclHandler, SAXDeclHandler,
SAXDTDHandler, SAXDTDHandler,
SAXEntityResolver,
SAXErrorHandler, SAXErrorHandler,
SAXLexicalHandler, SAXLexicalHandler,
SAXHandler_Last SAXHandler_Last
}; };
struct saxhandler_iface struct saxanyhandler_iface
{ {
IUnknown *handler; IUnknown *handler;
IUnknown *vbhandler; IUnknown *vbhandler;
@ -200,6 +201,23 @@ struct saxlexicalhandler_iface
IVBSAXLexicalHandler *vbhandler; IVBSAXLexicalHandler *vbhandler;
}; };
struct saxentityresolver_iface
{
ISAXEntityResolver *handler;
IVBSAXEntityResolver *vbhandler;
};
struct saxhandler_iface
{
union {
struct saxcontenthandler_iface content;
struct saxentityresolver_iface entityresolver;
struct saxerrorhandler_iface error;
struct saxlexicalhandler_iface lexical;
struct saxanyhandler_iface anyhandler;
} u;
};
typedef struct typedef struct
{ {
DispatchEx dispex; DispatchEx dispex;
@ -218,7 +236,7 @@ typedef struct
static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb) static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb)
{ {
struct saxhandler_iface *iface = &reader->saxhandlers[type]; struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
IUnknown *unk = (IUnknown*)ptr; IUnknown *unk = (IUnknown*)ptr;
if (unk) if (unk)
@ -237,7 +255,7 @@ static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type typ
static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret) static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret)
{ {
const struct saxhandler_iface *iface = &reader->saxhandlers[type]; const struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
if (!ret) return E_POINTER; if (!ret) return E_POINTER;
@ -256,17 +274,17 @@ static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_ty
static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader) static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader)
{ {
return (struct saxcontenthandler_iface*)&reader->saxhandlers[SAXContentHandler]; return &reader->saxhandlers[SAXContentHandler].u.content;
} }
static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader) static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader)
{ {
return (struct saxerrorhandler_iface*)&reader->saxhandlers[SAXErrorHandler]; return &reader->saxhandlers[SAXErrorHandler].u.error;
} }
static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader) static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader)
{ {
return (struct saxlexicalhandler_iface*)&reader->saxhandlers[SAXLexicalHandler]; return &reader->saxhandlers[SAXLexicalHandler].u.lexical;
} }
typedef struct typedef struct
@ -279,8 +297,8 @@ typedef struct
saxreader *saxreader; saxreader *saxreader;
HRESULT ret; HRESULT ret;
xmlParserCtxtPtr pParserCtxt; xmlParserCtxtPtr pParserCtxt;
WCHAR *publicId; BSTR publicId;
WCHAR *systemId; BSTR systemId;
int line; int line;
int column; int column;
BOOL vbInterface; BOOL vbInterface;
@ -330,8 +348,23 @@ static inline saxlocator *impl_from_ISAXAttributes( ISAXAttributes *iface )
static inline int saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type) static inline int saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
{ {
return (locator->vbInterface && locator->saxreader->saxhandlers[type].vbhandler) || struct saxanyhandler_iface *iface = &locator->saxreader->saxhandlers[type].u.anyhandler;
(!locator->vbInterface && locator->saxreader->saxhandlers[type].handler); return (locator->vbInterface && iface->vbhandler) || (!locator->vbInterface && iface->handler);
}
static HRESULT saxreader_saxcharacters(saxlocator *locator, BSTR chars)
{
struct saxcontenthandler_iface *content = saxreader_get_contenthandler(locator->saxreader);
HRESULT hr;
if (!saxreader_has_handler(locator, SAXContentHandler)) return S_OK;
if (locator->vbInterface)
hr = IVBSAXContentHandler_characters(content->vbhandler, &chars);
else
hr = ISAXContentHandler_characters(content->handler, chars, SysStringLen(chars));
return hr;
} }
/* property names */ /* property names */
@ -1550,7 +1583,6 @@ static void libxmlCharacters(
int len) int len)
{ {
saxlocator *This = ctx; saxlocator *This = ctx;
struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
BSTR Chars; BSTR Chars;
HRESULT hr; HRESULT hr;
xmlChar *cur, *end; xmlChar *cur, *end;
@ -1609,10 +1641,7 @@ static void libxmlCharacters(
} }
Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur); Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
if(This->vbInterface) hr = saxreader_saxcharacters(This, Chars);
hr = IVBSAXContentHandler_characters(handler->vbhandler, &Chars);
else
hr = ISAXContentHandler_characters(handler->handler, Chars, SysStringLen(Chars));
if (sax_callback_failed(This, hr)) if (sax_callback_failed(This, hr))
{ {
@ -1745,33 +1774,58 @@ static void libxmlFatalError(void *ctx, const char *msg, ...)
This->ret = E_FAIL; This->ret = E_FAIL;
} }
static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len) /* The only reason this helper exists is that CDATA section are reported by chunks,
{ newlines are used as delimiter. More than that, reader even alters input data before reporting.
saxlocator *This = ctx;
struct saxcontenthandler_iface *content = saxreader_get_contenthandler(This->saxreader);
struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(This->saxreader);
HRESULT hr = S_OK;
xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur-len;
xmlChar *cur, *end;
int realLen;
BSTR Chars;
BOOL lastEvent = FALSE, change;
update_position(This, FALSE); This helper should be called for substring with trailing newlines.
while(beg-9>=This->pParserCtxt->input->base */
&& memcmp(beg-9, "<![CDATA[", sizeof(char[9]))) static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
{ {
if(*beg=='\n' || (*beg=='\r' && *(beg+1)!='\n')) BSTR bstr = bstr_from_xmlCharN(str, len), ret;
This->line--; WCHAR *ptr;
beg--;
ptr = bstr + len - 1;
while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
ptr--;
while (*++ptr)
{
/* replace returns as:
- "\r<char>" -> "\n<char>"
- "\r\r" -> "\r"
- "\r\n" -> "\n"
*/
if (*ptr == '\r')
{
if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
{
/* shift tail */
memmove(ptr, ptr+1, len-- - (ptr-bstr));
}
else
*ptr = '\n';
}
} }
This->column = 0;
for(; beg>=This->pParserCtxt->input->base && *beg!='\n' && *beg!='\r'; beg--)
This->column++;
if (saxreader_has_handler(This, SAXLexicalHandler)) ret = SysAllocStringLen(bstr, len);
SysFreeString(bstr);
return ret;
}
static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
{ {
if (This->vbInterface) const xmlChar *start, *end;
saxlocator *locator = ctx;
struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
HRESULT hr = S_OK;
BSTR chars;
int i;
update_position(locator, FALSE);
if (saxreader_has_handler(locator, SAXLexicalHandler))
{
if (locator->vbInterface)
hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler); hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
else else
hr = ISAXLexicalHandler_startCDATA(lexical->handler); hr = ISAXLexicalHandler_startCDATA(lexical->handler);
@ -1779,61 +1833,66 @@ static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
if(FAILED(hr)) if(FAILED(hr))
{ {
format_error_message_from_id(This, hr); format_error_message_from_id(locator, hr);
return; return;
} }
realLen = This->pParserCtxt->input->cur-beg-3; start = value;
cur = beg; end = NULL;
end = beg; i = 0;
while(1) while (i < len)
{ {
while(end-beg<realLen && *end!='\r') end++; /* scan for newlines */
if(end-beg==realLen) if (value[i] == '\r' || value[i] == '\n')
{ {
end--; /* skip newlines/linefeeds */
lastEvent = TRUE; while (i < len)
{
if (value[i] != '\r' && value[i] != '\n') break;
i++;
} }
else if(end-beg==realLen-1 && *end=='\r' && *(end+1)=='\n') end = &value[i];
lastEvent = TRUE;
if(*end == '\r') change = TRUE; /* report */
else change = FALSE; chars = saxreader_get_cdata_chunk(start, end-start);
TRACE("(chunk %s)\n", debugstr_w(chars));
hr = saxreader_saxcharacters(locator, chars);
SysFreeString(chars);
if(change) *end = '\n'; start = &value[i];
end = NULL;
if (saxreader_has_handler(This, SAXContentHandler)) }
{ i++;
Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur+1); locator->column++;
if (This->vbInterface)
hr = IVBSAXContentHandler_characters(content->vbhandler, &Chars);
else
hr = ISAXContentHandler_characters(content->handler, Chars, SysStringLen(Chars));
} }
if(change) *end = '\r'; /* no newline chars (or last chunk) report as a whole */
if (!end && start == value)
if(lastEvent) {
break; /* report */
chars = bstr_from_xmlCharN(start, len-(start-value));
This->column += end-cur+2; TRACE("(%s)\n", debugstr_w(chars));
end += 2; hr = saxreader_saxcharacters(locator, chars);
cur = end; SysFreeString(chars);
} }
if (saxreader_has_handler(This, SAXLexicalHandler)) if (saxreader_has_handler(locator, SAXLexicalHandler))
{ {
if (This->vbInterface) if (locator->vbInterface)
hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler); hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
else else
hr = ISAXLexicalHandler_endCDATA(lexical->handler); hr = ISAXLexicalHandler_endCDATA(lexical->handler);
} }
if(FAILED(hr)) if(FAILED(hr))
format_error_message_from_id(This, hr); format_error_message_from_id(locator, hr);
}
This->column += 4+end-cur; static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
{
FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
return xmlSAX2ResolveEntity(ctx, publicid, systemid);
} }
/*** IVBSAXLocator interface ***/ /*** IVBSAXLocator interface ***/
@ -2123,7 +2182,7 @@ static HRESULT WINAPI isaxlocator_getPublicId(
publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt)); publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
if(SysStringLen(publicId)) if(SysStringLen(publicId))
This->publicId = (WCHAR*)&publicId; This->publicId = publicId;
else else
{ {
SysFreeString(publicId); SysFreeString(publicId);
@ -2145,7 +2204,7 @@ static HRESULT WINAPI isaxlocator_getSystemId(
systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt)); systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
if(SysStringLen(systemId)) if(SysStringLen(systemId))
This->systemId = (WCHAR*)&systemId; This->systemId = systemId;
else else
{ {
SysFreeString(systemId); SysFreeString(systemId);
@ -2370,24 +2429,6 @@ static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream,
return hr; return hr;
} }
static HRESULT internal_getEntityResolver(
saxreader *This,
void *pEntityResolver,
BOOL vbInterface)
{
FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
return E_NOTIMPL;
}
static HRESULT internal_putEntityResolver(
saxreader *This,
void *pEntityResolver,
BOOL vbInterface)
{
FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
return E_NOTIMPL;
}
static HRESULT internal_parse( static HRESULT internal_parse(
saxreader* This, saxreader* This,
VARIANT varInput, VARIANT varInput,
@ -2737,7 +2778,7 @@ static ULONG WINAPI saxxmlreader_Release(
for (i = 0; i < SAXHandler_Last; i++) for (i = 0; i < SAXHandler_Last; i++)
{ {
struct saxhandler_iface *iface = &This->saxhandlers[i]; struct saxanyhandler_iface *iface = &This->saxhandlers[i].u.anyhandler;
if (iface->handler) if (iface->handler)
IUnknown_Release(iface->handler); IUnknown_Release(iface->handler);
@ -2870,18 +2911,18 @@ static HRESULT WINAPI saxxmlreader_putProperty(
static HRESULT WINAPI saxxmlreader_get_entityResolver( static HRESULT WINAPI saxxmlreader_get_entityResolver(
IVBSAXXMLReader* iface, IVBSAXXMLReader* iface,
IVBSAXEntityResolver **pEntityResolver) IVBSAXEntityResolver **resolver)
{ {
saxreader *This = impl_from_IVBSAXXMLReader( iface ); saxreader *This = impl_from_IVBSAXXMLReader( iface );
return internal_getEntityResolver(This, pEntityResolver, TRUE); return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
} }
static HRESULT WINAPI saxxmlreader_put_entityResolver( static HRESULT WINAPI saxxmlreader_put_entityResolver(
IVBSAXXMLReader* iface, IVBSAXXMLReader* iface,
IVBSAXEntityResolver *pEntityResolver) IVBSAXEntityResolver *resolver)
{ {
saxreader *This = impl_from_IVBSAXXMLReader( iface ); saxreader *This = impl_from_IVBSAXXMLReader( iface );
return internal_putEntityResolver(This, pEntityResolver, TRUE); return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
} }
static HRESULT WINAPI saxxmlreader_get_contentHandler( static HRESULT WINAPI saxxmlreader_get_contentHandler(
@ -3077,18 +3118,18 @@ static HRESULT WINAPI isaxxmlreader_putProperty(
static HRESULT WINAPI isaxxmlreader_getEntityResolver( static HRESULT WINAPI isaxxmlreader_getEntityResolver(
ISAXXMLReader* iface, ISAXXMLReader* iface,
ISAXEntityResolver **ppEntityResolver) ISAXEntityResolver **resolver)
{ {
saxreader *This = impl_from_ISAXXMLReader( iface ); saxreader *This = impl_from_ISAXXMLReader( iface );
return internal_getEntityResolver(This, ppEntityResolver, FALSE); return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
} }
static HRESULT WINAPI isaxxmlreader_putEntityResolver( static HRESULT WINAPI isaxxmlreader_putEntityResolver(
ISAXXMLReader* iface, ISAXXMLReader* iface,
ISAXEntityResolver *pEntityResolver) ISAXEntityResolver *resolver)
{ {
saxreader *This = impl_from_ISAXXMLReader( iface ); saxreader *This = impl_from_ISAXXMLReader( iface );
return internal_putEntityResolver(This, pEntityResolver, FALSE); return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
} }
static HRESULT WINAPI isaxxmlreader_getContentHandler( static HRESULT WINAPI isaxxmlreader_getContentHandler(
@ -3256,7 +3297,8 @@ HRESULT SAXXMLReader_create(MSXML_VERSION version, IUnknown *outer, LPVOID *ppOb
reader->sax.comment = libxmlComment; reader->sax.comment = libxmlComment;
reader->sax.error = libxmlFatalError; reader->sax.error = libxmlFatalError;
reader->sax.fatalError = libxmlFatalError; reader->sax.fatalError = libxmlFatalError;
reader->sax.cdataBlock = libxmlCDataBlock; reader->sax.cdataBlock = libxml_cdatablock;
reader->sax.resolveEntity = libxmlresolveentity;
*ppObj = &reader->IVBSAXXMLReader_iface; *ppObj = &reader->IVBSAXXMLReader_iface;

View file

@ -103,6 +103,9 @@ typedef struct
MSXML_VERSION version; MSXML_VERSION version;
xmlHashTablePtr cache; xmlHashTablePtr cache;
xmlChar **uris;
int allocated;
int count;
VARIANT_BOOL validateOnLoad; VARIANT_BOOL validateOnLoad;
int read_only; int read_only;
@ -116,12 +119,6 @@ typedef struct
LONG ref; LONG ref;
} cache_entry; } cache_entry;
typedef struct
{
LONG index;
BSTR* out;
} cache_index_data;
/* datatypes lookup stuff /* datatypes lookup stuff
* generated with help from gperf */ * generated with help from gperf */
#define DT_MIN_STR_LEN 2 #define DT_MIN_STR_LEN 2
@ -744,7 +741,7 @@ void schemasInit(void)
return; return;
} }
buf = LockResource(datatypes_handle); buf = LockResource(datatypes_handle);
datatypes_len = SizeofResource(MSXML_hInstance, datatypes_rsrc) - 1; datatypes_len = SizeofResource(MSXML_hInstance, datatypes_rsrc);
/* Resource is loaded as raw data, /* Resource is loaded as raw data,
* need a null-terminated string */ * need a null-terminated string */
@ -844,7 +841,7 @@ static BOOL link_datatypes(xmlDocPtr schema)
xmlNodePtr root, next, child; xmlNodePtr root, next, child;
xmlNsPtr ns; xmlNsPtr ns;
assert((void*)xmlGetExternalEntityLoader() == (void*)external_entity_loader); assert(xmlGetExternalEntityLoader() == external_entity_loader);
root = xmlDocGetRootElement(schema); root = xmlDocGetRootElement(schema);
if (!root) if (!root)
return FALSE; return FALSE;
@ -985,6 +982,55 @@ static void cache_free(void* data, xmlChar* name /* ignored */)
cache_entry_release((cache_entry*)data); cache_entry_release((cache_entry*)data);
} }
/* returns index or -1 if not found */
static int cache_free_uri(schema_cache *cache, const xmlChar *uri)
{
int i;
for (i = 0; i < cache->count; i++)
if (xmlStrEqual(cache->uris[i], uri))
{
heap_free(cache->uris[i]);
return i;
}
return -1;
}
static void cache_add_entry(schema_cache *cache, const xmlChar *uri, cache_entry *entry)
{
int i;
/* meaning no entry found with this name */
if (xmlHashRemoveEntry(cache->cache, uri, cache_free))
{
if (cache->count == cache->allocated)
{
cache->allocated *= 2;
cache->uris = heap_realloc(cache->uris, cache->allocated*sizeof(xmlChar*));
}
i = cache->count++;
}
else
i = cache_free_uri(cache, uri);
cache->uris[i] = heap_strdupxmlChar(uri);
xmlHashAddEntry(cache->cache, uri, entry);
}
static void cache_remove_entry(schema_cache *cache, const xmlChar *uri)
{
/* adjust index if entry was really removed */
if (xmlHashRemoveEntry(cache->cache, uri, cache_free) == 0)
{
int i = cache_free_uri(cache, uri);
if (i == -1) return;
/* shift array */
if (i != --cache->count)
memmove(&cache->uris[i], &cache->uris[i+1], (cache->count-i)*sizeof(xmlChar*));
}
}
/* This one adds all namespaces defined in document to a cache, without anything /* This one adds all namespaces defined in document to a cache, without anything
associated with uri obviously. associated with uri obviously.
Unfortunately namespace:: axis implementation in libxml2 differs from what we need, Unfortunately namespace:: axis implementation in libxml2 differs from what we need,
@ -1033,8 +1079,7 @@ HRESULT cache_from_doc_ns(IXMLDOMSchemaCollection2 *iface, xmlnode *node)
entry->schema = NULL; entry->schema = NULL;
entry->doc = NULL; entry->doc = NULL;
xmlHashRemoveEntry(This->cache, ns->href, cache_free); cache_add_entry(This, ns->href, entry);
xmlHashAddEntry(This->cache, ns->href, entry);
} }
pos++; pos++;
} }
@ -1091,6 +1136,11 @@ static ULONG WINAPI schema_cache_Release(IXMLDOMSchemaCollection2* iface)
if (ref == 0) 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); xmlHashFree(This->cache, cache_free);
release_dispex(&This->dispex); release_dispex(&This->dispex);
heap_free(This); heap_free(This);
@ -1146,7 +1196,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
{ {
case VT_NULL: case VT_NULL:
{ {
xmlHashRemoveEntry(This->cache, name, cache_free); cache_remove_entry(This, name);
} }
break; break;
@ -1164,8 +1214,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
return E_FAIL; return E_FAIL;
} }
xmlHashRemoveEntry(This->cache, name, cache_free); cache_add_entry(This, name, entry);
xmlHashAddEntry(This->cache, name, entry);
} }
break; break;
@ -1214,8 +1263,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
return E_FAIL; return E_FAIL;
} }
xmlHashRemoveEntry(This->cache, name, cache_free); cache_add_entry(This, name, entry);
xmlHashAddEntry(This->cache, name, entry);
} }
break; break;
@ -1263,7 +1311,7 @@ static HRESULT WINAPI schema_cache_remove(IXMLDOMSchemaCollection2* iface, BSTR
if (This->version == MSXML6) return E_NOTIMPL; if (This->version == MSXML6) return E_NOTIMPL;
xmlHashRemoveEntry(This->cache, name, cache_free); cache_remove_entry(This, name);
heap_free(name); heap_free(name);
return S_OK; return S_OK;
} }
@ -1275,33 +1323,25 @@ static HRESULT WINAPI schema_cache_get_length(IXMLDOMSchemaCollection2* iface, L
if (!length) if (!length)
return E_POINTER; return E_POINTER;
*length = xmlHashSize(This->cache);
*length = This->count;
return S_OK; return S_OK;
} }
static void cache_index(void* data /* ignored */, void* index, xmlChar* name)
{
cache_index_data* index_data = (cache_index_data*)index;
if (index_data->index-- == 0)
*index_data->out = bstr_from_xmlChar(name);
}
static HRESULT WINAPI schema_cache_get_namespaceURI(IXMLDOMSchemaCollection2* iface, static HRESULT WINAPI schema_cache_get_namespaceURI(IXMLDOMSchemaCollection2* iface,
LONG index, BSTR* len) LONG index, BSTR* uri)
{ {
schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
cache_index_data data = {index, len};
TRACE("(%p)->(%i %p)\n", This, index, len);
if (!len) TRACE("(%p)->(%i %p)\n", This, index, uri);
if (!uri)
return E_POINTER; return E_POINTER;
if (index >= xmlHashSize(This->cache)) if (index >= This->count)
return E_FAIL; return E_FAIL;
*len = NULL; *uri = bstr_from_xmlChar(This->uris[index]);
xmlHashScan(This->cache, cache_index, &data);
return S_OK; return S_OK;
} }
@ -1313,7 +1353,7 @@ static void cache_copy(void* data, void* dest, xmlChar* name)
if (xmlHashLookup(This->cache, name) == NULL) if (xmlHashLookup(This->cache, name) == NULL)
{ {
cache_entry_add_ref(entry); cache_entry_add_ref(entry);
xmlHashAddEntry(This->cache, name, entry); cache_add_entry(This, name, entry);
} }
} }
@ -1531,6 +1571,9 @@ HRESULT SchemaCache_create(MSXML_VERSION version, IUnknown* outer, void** obj)
This->IXMLDOMSchemaCollection2_iface.lpVtbl = &XMLDOMSchemaCollection2Vtbl; This->IXMLDOMSchemaCollection2_iface.lpVtbl = &XMLDOMSchemaCollection2Vtbl;
This->cache = xmlHashCreate(DEFAULT_HASHTABLE_SIZE); This->cache = xmlHashCreate(DEFAULT_HASHTABLE_SIZE);
This->allocated = 10;
This->count = 0;
This->uris = heap_alloc(This->allocated*sizeof(xmlChar*));
This->ref = 1; This->ref = 1;
This->version = version; This->version = version;
This->validateOnLoad = VARIANT_TRUE; This->validateOnLoad = VARIANT_TRUE;

View file

@ -29,6 +29,7 @@
//#include <stdarg.h> //#include <stdarg.h>
#ifdef HAVE_LIBXML2 #ifdef HAVE_LIBXML2
# include <libxml/parser.h> # include <libxml/parser.h>
# include <libxml/parserInternals.h>
//# include <libxml/xmlerror.h> //# include <libxml/xmlerror.h>
#endif #endif
@ -58,6 +59,11 @@ static inline domtext *impl_from_IXMLDOMText( IXMLDOMText *iface )
return CONTAINING_RECORD(iface, domtext, IXMLDOMText_iface); return CONTAINING_RECORD(iface, domtext, IXMLDOMText_iface);
} }
static void domtext_reset_noenc(domtext *This)
{
This->node.node->name = NULL;
}
static HRESULT WINAPI domtext_QueryInterface( static HRESULT WINAPI domtext_QueryInterface(
IXMLDOMText *iface, IXMLDOMText *iface,
REFIID riid, REFIID riid,
@ -185,6 +191,7 @@ static HRESULT WINAPI domtext_put_nodeValue(
TRACE("(%p)->(%s)\n", This, debugstr_variant(&value)); TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
domtext_reset_noenc(This);
return node_put_value(&This->node, &value); return node_put_value(&This->node, &value);
} }
@ -374,6 +381,7 @@ static HRESULT WINAPI domtext_put_text(
{ {
domtext *This = impl_from_IXMLDOMText( iface ); domtext *This = impl_from_IXMLDOMText( iface );
TRACE("(%p)->(%s)\n", This, debugstr_w(p)); TRACE("(%p)->(%s)\n", This, debugstr_w(p));
domtext_reset_noenc(This);
return node_put_text( &This->node, p ); return node_put_text( &This->node, p );
} }
@ -611,7 +619,14 @@ static HRESULT WINAPI domtext_put_data(
BSTR data) BSTR data)
{ {
domtext *This = impl_from_IXMLDOMText( iface ); domtext *This = impl_from_IXMLDOMText( iface );
static WCHAR rnW[] = {'\r','\n',0};
TRACE("(%p)->(%s)\n", This, debugstr_w(data)); TRACE("(%p)->(%s)\n", This, debugstr_w(data));
if (data && !strcmpW(rnW, data))
This->node.node->name = xmlStringTextNoenc;
else
domtext_reset_noenc(This);
return node_set_content(&This->node, data); return node_set_content(&This->node, data);
} }

View file

@ -49,6 +49,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
typedef struct _xmlparser typedef struct _xmlparser
{ {
IXMLParser IXMLParser_iface; IXMLParser IXMLParser_iface;
IXMLNodeFactory *nodefactory;
IUnknown *input;
LONG ref; LONG ref;
int flags; int flags;
@ -98,6 +100,12 @@ static ULONG WINAPI xmlparser_Release(IXMLParser* iface)
TRACE("(%p)->(%d)\n", This, ref); TRACE("(%p)->(%d)\n", This, ref);
if ( ref == 0 ) if ( ref == 0 )
{ {
if(This->input)
IUnknown_Release(This->input);
if(This->nodefactory)
IXMLNodeFactory_Release(This->nodefactory);
heap_free( This ); heap_free( This );
} }
@ -109,18 +117,33 @@ static HRESULT WINAPI xmlparser_SetFactory(IXMLParser *iface, IXMLNodeFactory *p
{ {
xmlparser *This = impl_from_IXMLParser( iface ); xmlparser *This = impl_from_IXMLParser( iface );
FIXME("(%p %p)\n", This, pNodeFactory); TRACE("(%p %p)\n", This, pNodeFactory);
return E_NOTIMPL; if(This->nodefactory)
IXMLNodeFactory_Release(This->nodefactory);
This->nodefactory = pNodeFactory;
if(This->nodefactory)
IXMLNodeFactory_AddRef(This->nodefactory);
return S_OK;
} }
static HRESULT WINAPI xmlparser_GetFactory(IXMLParser *iface, IXMLNodeFactory **ppNodeFactory) static HRESULT WINAPI xmlparser_GetFactory(IXMLParser *iface, IXMLNodeFactory **ppNodeFactory)
{ {
xmlparser *This = impl_from_IXMLParser( iface ); xmlparser *This = impl_from_IXMLParser( iface );
FIXME("(%p, %p)\n", This, ppNodeFactory); TRACE("(%p, %p)\n", This, ppNodeFactory);
return E_NOTIMPL; if(!ppNodeFactory)
return E_INVALIDARG;
*ppNodeFactory = This->nodefactory;
if(*ppNodeFactory)
IXMLNodeFactory_AddRef(*ppNodeFactory);
return S_OK;
} }
static HRESULT WINAPI xmlparser_Abort(IXMLParser *iface, BSTR bstrErrorInfo) static HRESULT WINAPI xmlparser_Abort(IXMLParser *iface, BSTR bstrErrorInfo)
@ -230,9 +253,18 @@ static HRESULT WINAPI xmlparser_SetInput(IXMLParser *iface, IUnknown *pStm)
{ {
xmlparser *This = impl_from_IXMLParser( iface ); xmlparser *This = impl_from_IXMLParser( iface );
FIXME("(%p %p)\n", This, pStm); TRACE("(%p %p)\n", This, pStm);
return E_NOTIMPL; if(!pStm)
return E_INVALIDARG;
if(This->input)
IUnknown_Release(This->input);
This->input = pStm;
IUnknown_AddRef(This->input);
return S_OK;
} }
static HRESULT WINAPI xmlparser_PushData(IXMLParser *iface, const char *pData, static HRESULT WINAPI xmlparser_PushData(IXMLParser *iface, const char *pData,
@ -418,6 +450,8 @@ HRESULT XMLParser_create(IUnknown* pUnkOuter, void**ppObj)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
This->IXMLParser_iface.lpVtbl = &xmlparser_vtbl; This->IXMLParser_iface.lpVtbl = &xmlparser_vtbl;
This->nodefactory = NULL;
This->input = NULL;
This->flags = 0; This->flags = 0;
This->ref = 1; This->ref = 1;

View file

@ -58,7 +58,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
%option reentrant bison-bridge %option reentrant bison-bridge
%option noyywrap %option noyywrap
%option prefix="xslpattern_" %option prefix="xslpattern_"
%option noinput nounput %option noinput nounput never-interactive
/* From the w3c XML standard /* From the w3c XML standard
* <http://www.w3.org/TR/REC-xml/> */ * <http://www.w3.org/TR/REC-xml/> */

View file

@ -872,16 +872,12 @@ yy_match:
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp; ++yy_cp;
} }
while ( yy_base[yy_current_state] != 138 ); while ( yy_current_state != 95 );
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
yy_find_action: yy_find_action:
yy_act = yy_accept[yy_current_state]; yy_act = yy_accept[yy_current_state];
if ( yy_act == 0 )
{ /* have to back up */
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
yy_act = yy_accept[yy_current_state];
}
YY_DO_BEFORE_ACTION; YY_DO_BEFORE_ACTION;
@ -1088,7 +1084,7 @@ YY_RULE_SETUP
#line 153 "xslpattern.l" #line 153 "xslpattern.l"
ECHO; ECHO;
YY_BREAK YY_BREAK
#line 1092 "xslpattern.yy.c" #line 1088 "xslpattern.yy.c"
case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(INITIAL):
yyterminate(); yyterminate();
@ -1155,7 +1151,8 @@ case YY_STATE_EOF(INITIAL):
else else
{ {
yy_cp = yyg->yy_c_buf_p; yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
goto yy_find_action; goto yy_find_action;
} }
} }
@ -1609,10 +1606,6 @@ static void xslpattern__load_buffer_state (yyscan_t yyscanner)
xslpattern_free((void *) b ,yyscanner ); xslpattern_free((void *) b ,yyscanner );
} }
#ifndef __cplusplus
extern int isatty (int );
#endif /* __cplusplus */
/* Initializes or reinitializes a buffer. /* Initializes or reinitializes a buffer.
* This function is sometimes called more than once on the same buffer, * This function is sometimes called more than once on the same buffer,
* such as during a xslpattern_restart() or at EOF. * such as during a xslpattern_restart() or at EOF.
@ -1637,7 +1630,7 @@ extern int isatty (int );
b->yy_bs_column = 0; b->yy_bs_column = 0;
} }
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; b->yy_is_interactive = 0;
errno = oerrno; errno = oerrno;
} }

View file

@ -120,7 +120,7 @@ reactos/dll/win32/msvfw32 # Autosync
reactos/dll/win32/msvidc32 # Autosync reactos/dll/win32/msvidc32 # Autosync
reactos/dll/win32/msxml # Synced to Wine-1.5.19 reactos/dll/win32/msxml # Synced to Wine-1.5.19
reactos/dll/win32/msxml2 # Synced to Wine-1.5.19 reactos/dll/win32/msxml2 # Synced to Wine-1.5.19
reactos/dll/win32/msxml3 # Synced to Wine-1.5.12 reactos/dll/win32/msxml3 # Synced to Wine-1.5.26
reactos/dll/win32/msxml4 # Synced to Wine-1.5.19 reactos/dll/win32/msxml4 # Synced to Wine-1.5.19
reactos/dll/win32/msxml6 # Synced to Wine-1.5.19 reactos/dll/win32/msxml6 # Synced to Wine-1.5.19
reactos/dll/win32/nddeapi # Synced to Wine-1.5.19 reactos/dll/win32/nddeapi # Synced to Wine-1.5.19