diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index b4b89624f64..af5097cfe5d 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -168,6 +168,7 @@ static bsc domdoc_bsc = { &bsc_vtbl }; typedef struct _domdoc { const struct IXMLDOMDocument2Vtbl *lpVtbl; + const struct IPersistStreamVtbl *lpvtblIPersistStream; LONG ref; VARIANT_BOOL async; VARIANT_BOOL validating; @@ -178,6 +179,9 @@ typedef struct _domdoc IXMLDOMNode *node; IXMLDOMSchemaCollection *schema; HRESULT error; + + /* IPersistStream */ + IStream *stream; } domdoc; LONG xmldoc_add_ref(xmlDocPtr doc) @@ -210,6 +214,131 @@ static inline xmlDocPtr get_doc( domdoc *This ) return (xmlDocPtr) xmlNodePtr_from_domnode( This->node, XML_DOCUMENT_NODE ); } +static inline domdoc *impl_from_IPersistStream(IPersistStream *iface) +{ + return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStream)); +} + +/************************************************************************ + * xmldoc implementation of IPersistStream. + */ +static HRESULT WINAPI xmldoc_IPersistStream_QueryInterface( + IPersistStream *iface, REFIID riid, LPVOID *ppvObj) +{ + domdoc *this = impl_from_IPersistStream(iface); + return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj); +} + +static ULONG WINAPI xmldoc_IPersistStream_AddRef( + IPersistStream *iface) +{ + domdoc *this = impl_from_IPersistStream(iface); + return IXMLDocument_AddRef((IXMLDocument *)this); +} + +static ULONG WINAPI xmldoc_IPersistStream_Release( + IPersistStream *iface) +{ + domdoc *this = impl_from_IPersistStream(iface); + return IXMLDocument_Release((IXMLDocument *)this); +} + +static HRESULT WINAPI xmldoc_IPersistStream_GetClassID( + IPersistStream *iface, CLSID *classid) +{ + FIXME("(%p,%p): stub!\n", iface, classid); + return E_NOTIMPL; +} + +static HRESULT WINAPI xmldoc_IPersistStream_IsDirty( + IPersistStream *iface) +{ + domdoc *This = impl_from_IPersistStream(iface); + + FIXME("(%p->%p): stub!\n", iface, This); + + return S_FALSE; +} + +static HRESULT WINAPI xmldoc_IPersistStream_Load( + IPersistStream *iface, LPSTREAM pStm) +{ + domdoc *This = impl_from_IPersistStream(iface); + HRESULT hr; + HGLOBAL hglobal; + DWORD read, written, len; + BYTE buf[4096]; + char *ptr; + xmlDocPtr xmldoc = NULL; + + TRACE("(%p, %p)\n", iface, pStm); + + if (!pStm) + return E_INVALIDARG; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream); + if (FAILED(hr)) + return hr; + + do + { + IStream_Read(pStm, buf, sizeof(buf), &read); + hr = IStream_Write(This->stream, buf, read, &written); + } while(SUCCEEDED(hr) && written != 0 && read != 0); + + if (FAILED(hr)) + { + ERR("Failed to copy stream\n"); + return hr; + } + + hr = GetHGlobalFromStream(This->stream, &hglobal); + if (FAILED(hr)) + return hr; + + len = GlobalSize(hglobal); + ptr = GlobalLock(hglobal); + if (len != 0) + xmldoc = parse_xml(ptr, len); + GlobalUnlock(hglobal); + + if (!xmldoc) + { + ERR("Failed to parse xml\n"); + return E_FAIL; + } + + attach_xmlnode( This->node, (xmlNodePtr)xmldoc ); + + return S_OK; +} + +static HRESULT WINAPI xmldoc_IPersistStream_Save( + IPersistStream *iface, LPSTREAM pStm, BOOL fClearDirty) +{ + FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty); + return E_NOTIMPL; +} + +static HRESULT WINAPI xmldoc_IPersistStream_GetSizeMax( + IPersistStream *iface, ULARGE_INTEGER *pcbSize) +{ + TRACE("(%p, %p): stub!\n", iface, pcbSize); + return E_NOTIMPL; +} + +static const IPersistStreamVtbl xmldoc_IPersistStream_VTable = +{ + xmldoc_IPersistStream_QueryInterface, + xmldoc_IPersistStream_AddRef, + xmldoc_IPersistStream_Release, + xmldoc_IPersistStream_GetClassID, + xmldoc_IPersistStream_IsDirty, + xmldoc_IPersistStream_Load, + xmldoc_IPersistStream_Save, + xmldoc_IPersistStream_GetSizeMax, +}; + static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject ) { domdoc *This = impl_from_IXMLDOMDocument2( iface ); @@ -227,6 +356,10 @@ static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID rii { return IUnknown_QueryInterface(This->node_unk, riid, ppvObject); } + else if (IsEqualGUID(&IID_IPersistStream, riid)) + { + *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream); + } else { FIXME("interface %s not implemented\n", debugstr_guid(riid)); @@ -261,6 +394,7 @@ static ULONG WINAPI domdoc_Release( { IUnknown_Release( This->node_unk ); if(This->schema) IXMLDOMSchemaCollection_Release( This->schema ); + if (This->stream) IStream_Release(This->stream); HeapFree( GetProcessHeap(), 0, This ); } @@ -1023,6 +1157,8 @@ static HRESULT WINAPI domdoc_load( LPWSTR filename = NULL; xmlDocPtr xmldoc = NULL; HRESULT hr = S_FALSE; + IXMLDOMDocument2 *pNewDoc = NULL; + IStream *pStream = NULL; TRACE("type %d\n", V_VT(&xmlSource) ); @@ -1036,7 +1172,59 @@ static HRESULT WINAPI domdoc_load( { case VT_BSTR: filename = V_BSTR(&xmlSource); - } + break; + case VT_UNKNOWN: + hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc); + if(hr == S_OK) + { + if(pNewDoc) + { + domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc ); + xmldoc = xmlCopyDoc(get_doc(newDoc), 1); + attach_xmlnode(This->node, (xmlNodePtr) xmldoc); + + *isSuccessful = VARIANT_TRUE; + + return S_OK; + } + } + hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream); + if(hr == S_OK) + { + IPersistStream *pDocStream; + hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream); + if(hr == S_OK) + { + hr = xmldoc_IPersistStream_Load(pDocStream, pStream); + IStream_Release(pStream); + if(hr == S_OK) + { + *isSuccessful = VARIANT_TRUE; + + TRACE("Using ID_IStream to load Document\n"); + return S_OK; + } + else + { + ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr); + } + } + else + { + ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr); + } + } + else + { + /* ISequentialStream */ + FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl); + } + break; + default: + FIXME("VT type not supported (%d)\n", V_VT(&xmlSource)); + } + + TRACE("filename (%s)\n", debugstr_w(filename)); if ( filename ) { @@ -1057,6 +1245,8 @@ static HRESULT WINAPI domdoc_load( xmldoc->_private = 0; attach_xmlnode(This->node, (xmlNodePtr) xmldoc); + TRACE("ret (%d)\n", hr); + return hr; } @@ -1562,6 +1752,7 @@ HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj) return E_OUTOFMEMORY; doc->lpVtbl = &domdoc_vtbl; + doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable; doc->ref = 1; doc->async = 0; doc->validating = 0; @@ -1570,6 +1761,7 @@ HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj) doc->bUseXPath = FALSE; doc->error = S_OK; doc->schema = NULL; + doc->stream = NULL; xmldoc = xmlNewDoc(NULL); if(!xmldoc) diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index 2d574ff8562..4914a58ee38 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -61,6 +61,8 @@ extern LONG xmldoc_release( xmlDocPtr doc ); extern HRESULT XMLElement_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj ); extern HRESULT XMLElementCollection_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj ); +extern xmlDocPtr parse_xml(char *ptr, int len); + #endif extern IXMLDOMParseError *create_parseError( LONG code, BSTR url, BSTR reason, BSTR srcText, diff --git a/dlls/msxml3/xmldoc.c b/dlls/msxml3/xmldoc.c index 6d44c785580..a4c0850b095 100644 --- a/dlls/msxml3/xmldoc.c +++ b/dlls/msxml3/xmldoc.c @@ -44,7 +44,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); /* FIXME: IXMLDocument needs to implement * - IXMLError * - IPersistMoniker - * - IPersistStream */ typedef struct _xmldoc @@ -79,11 +78,13 @@ static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, vo TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); if (IsEqualGUID(riid, &IID_IUnknown) || - IsEqualGUID(riid, &IID_IXMLDocument)) + IsEqualGUID(riid, &IID_IXMLDocument) || + IsEqualGUID(riid, &IID_IXMLDOMDocument)) { *ppvObject = iface; } - else if (IsEqualGUID(&IID_IPersistStreamInit, riid)) + else if (IsEqualGUID(&IID_IPersistStreamInit, riid) || + IsEqualGUID(&IID_IPersistStream, riid)) { *ppvObject = (IPersistStreamInit *)&(This->lpvtblIPersistStreamInit); } @@ -522,7 +523,7 @@ static HRESULT WINAPI xmldoc_IPersistStreamInit_IsDirty( return E_NOTIMPL; } -static xmlDocPtr parse_xml(char *ptr, int len) +xmlDocPtr parse_xml(char *ptr, int len) { #ifdef HAVE_XMLREADMEMORY return xmlReadMemory(ptr, len, NULL, NULL,