* 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,19 +556,28 @@ 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)
if (ref < 0)
WARN("negative refcount, expect troubles\n");
if (ref == 0)
{ {
orphan_entry *orphan, *orphan2; orphan_entry *orphan, *orphan2;
TRACE("freeing docptr %p\n", doc); TRACE("freeing docptr %p\n", doc);
@ -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);
return node_insert_before(&This->node, newChild, &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);
}
}
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,40 +2157,25 @@ 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);
}
}
else
{
ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
}
}
else
{ {
/* ISequentialStream */ hr = domdoc_load_from_stream(This, stream);
FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl); if (hr == S_OK)
*isSuccessful = VARIANT_TRUE;
ISequentialStream_Release(stream);
return hr;
} }
FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr, V_UNKNOWN(&source)->lpVtbl);
break; break;
default: }
FIXME("VT type not supported (%d)\n", V_VT(&source)); default:
FIXME("VT type not supported (%d)\n", V_VT(&source));
} }
if ( filename ) if ( filename )
@ -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,16 +1254,25 @@ static HRESULT WINAPI domelem_setAttribute(
if ( !element ) if ( !element )
return E_FAIL; return E_FAIL;
VariantInit(&var); if (V_VT(&value) != VT_BSTR)
hr = VariantChangeType(&var, &value, 0, VT_BSTR);
if(hr != S_OK)
{ {
FIXME("VariantChangeType failed\n"); VARIANT var;
return hr;
VariantInit(&var);
hr = VariantChangeType(&var, &value, 0, VT_BSTR);
if (hr != S_OK)
{
FIXME("VariantChangeType failed\n");
return hr;
}
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 ); xml_name = xmlchar_from_wchar( name );
xml_value = xmlchar_from_wchar( V_BSTR(&var) );
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,7 +194,8 @@ 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);
memcpy(ret, str, size); if(ret)
memcpy(ret, str, size);
} }
return ret; return ret;
@ -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,36 +285,48 @@ 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;
VariantInit(&string_value); if (V_VT(value) != VT_BSTR)
hr = VariantChangeType(&string_value, value, 0, VT_BSTR); {
if(FAILED(hr)) { VARIANT string_value;
WARN("Couldn't convert to VT_BSTR\n");
return hr;
}
hr = node_set_content(This, V_BSTR(&string_value)); VariantInit(&string_value);
VariantClear(&string_value); hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
if(FAILED(hr)) {
WARN("Couldn't convert to VT_BSTR\n");
return hr;
}
hr = node_set_content(This, V_BSTR(&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;
VariantInit(&string_value); if (V_VT(value) != VT_BSTR)
hr = VariantChangeType(&string_value, value, 0, VT_BSTR); {
if(FAILED(hr)) { VARIANT string_value;
WARN("Couldn't convert to VT_BSTR\n");
return hr;
}
hr = node_set_content_escaped(This, V_BSTR(&string_value)); VariantInit(&string_value);
VariantClear(&string_value); hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
if(FAILED(hr)) {
WARN("Couldn't convert to VT_BSTR\n");
return hr;
}
hr = node_set_content_escaped(This, V_BSTR(&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)
xmldoc_add_ref( node->doc ); {
xmlnode_add_ref(node);
xmldoc_add_ref(node->doc);
}
This->node = node; This->node = node;
This->iface = node_iface; This->iface = node_iface;

View file

@ -341,28 +341,62 @@ 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)
{ {
case INVOKE_PROPERTYGET: switch(flags)
{ {
IXMLDOMNode *disp = NULL; case DISPATCH_PROPERTYGET:
{
IXMLDOMNode *disp = NULL;
IXMLDOMNodeList_get_item(&This->IXMLDOMNodeList_iface, id - DISPID_DOM_COLLECTION_BASE, &disp); V_VT(res) = VT_DISPATCH;
V_DISPATCH(res) = (IDispatch*)disp; IXMLDOMNodeList_get_item(&This->IXMLDOMNodeList_iface, id - DISPID_DOM_COLLECTION_BASE, &disp);
break; V_DISPATCH(res) = (IDispatch*)disp;
} break;
default: }
{ default:
FIXME("unimplemented flags %x\n", flags); {
break; FIXME("unimplemented flags %x\n", flags);
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.
This helper should be called for substring with trailing newlines.
*/
static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
{ {
saxlocator *This = ctx; BSTR bstr = bstr_from_xmlCharN(str, len), ret;
struct saxcontenthandler_iface *content = saxreader_get_contenthandler(This->saxreader); WCHAR *ptr;
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); ptr = bstr + len - 1;
while(beg-9>=This->pParserCtxt->input->base while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
&& memcmp(beg-9, "<![CDATA[", sizeof(char[9]))) ptr--;
while (*++ptr)
{ {
if(*beg=='\n' || (*beg=='\r' && *(beg+1)!='\n')) /* replace returns as:
This->line--;
beg--; - "\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)
{
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 (This->vbInterface) 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++;
}
end = &value[i];
/* report */
chars = saxreader_get_cdata_chunk(start, end-start);
TRACE("(chunk %s)\n", debugstr_w(chars));
hr = saxreader_saxcharacters(locator, chars);
SysFreeString(chars);
start = &value[i];
end = NULL;
} }
else if(end-beg==realLen-1 && *end=='\r' && *(end+1)=='\n') i++;
lastEvent = TRUE; locator->column++;
if(*end == '\r') change = TRUE;
else change = FALSE;
if(change) *end = '\n';
if (saxreader_has_handler(This, SAXContentHandler))
{
Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur+1);
if (This->vbInterface)
hr = IVBSAXContentHandler_characters(content->vbhandler, &Chars);
else
hr = ISAXContentHandler_characters(content->handler, Chars, SysStringLen(Chars));
}
if(change) *end = '\r';
if(lastEvent)
break;
This->column += end-cur+2;
end += 2;
cur = end;
} }
if (saxreader_has_handler(This, SAXLexicalHandler)) /* no newline chars (or last chunk) report as a whole */
if (!end && start == value)
{ {
if (This->vbInterface) /* report */
chars = bstr_from_xmlCharN(start, len-(start-value));
TRACE("(%s)\n", debugstr_w(chars));
hr = saxreader_saxcharacters(locator, chars);
SysFreeString(chars);
}
if (saxreader_has_handler(locator, SAXLexicalHandler))
{
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