diff --git a/dlls/msxml3/xmldoc.c b/dlls/msxml3/xmldoc.c index e387921..ae1623d 100644 --- a/dlls/msxml3/xmldoc.c +++ b/dlls/msxml3/xmldoc.c @@ -51,6 +51,7 @@ typedef struct _xmldoc { const IXMLDocumentVtbl *lpVtbl; const IPersistStreamInitVtbl *lpvtblIPersistStreamInit; + const IPersistStreamVtbl *lpvtblIPersistStream; LONG ref; HRESULT error; @@ -72,14 +73,20 @@ static inline xmldoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface) return (xmldoc *)((char*)iface - FIELD_OFFSET(xmldoc, lpvtblIPersistStreamInit)); } +static inline xmldoc *impl_from_IPersistStream(IPersistStream *iface) +{ + return (xmldoc *)((char*)iface - FIELD_OFFSET(xmldoc, lpvtblIPersistStream)); +} + static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, void** ppvObject) { xmldoc *This = impl_from_IXMLDocument(iface); TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); - if (IsEqualGUID(riid, &IID_IUnknown) || - IsEqualGUID(riid, &IID_IXMLDocument)) + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IXMLDocument) || + IsEqualGUID(riid, &IID_IXMLDOMDocument)) { *ppvObject = iface; } @@ -87,6 +94,10 @@ static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, vo { *ppvObject = (IPersistStreamInit *)&(This->lpvtblIPersistStreamInit); } + else if (IsEqualGUID(&IID_IPersistStream, riid)) + { + *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream); + } else { FIXME("interface %s not implemented\n", debugstr_guid(riid)); @@ -619,6 +630,122 @@ static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable = xmldoc_IPersistStreamInit_InitNew }; +/************************************************************************ + * xmldoc implementation of IPersistStream. + */ +static HRESULT WINAPI xmldoc_IPersistStream_QueryInterface( + IPersistStream *iface, REFIID riid, LPVOID *ppvObj) +{ + xmldoc *this = impl_from_IPersistStream(iface); + return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj); +} + +static ULONG WINAPI xmldoc_IPersistStream_AddRef( + IPersistStream *iface) +{ + xmldoc *this = impl_from_IPersistStream(iface); + return IXMLDocument_AddRef((IXMLDocument *)this); +} + +static ULONG WINAPI xmldoc_IPersistStream_Release( + IPersistStream *iface) +{ + xmldoc *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) +{ + FIXME("(%p): stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI xmldoc_IPersistStream_Load( + IPersistStream *iface, LPSTREAM pStm) +{ + xmldoc *This = impl_from_IPersistStream(iface); + xmlNodePtr xmlnode; + HRESULT hr; + HGLOBAL hglobal; + DWORD read, written, len; + BYTE buf[4096]; + char *ptr; + + 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) + This->xmldoc = parse_xml(ptr, len); + GlobalUnlock(hglobal); + + if (!This->xmldoc) + { + ERR("Failed to parse xml\n"); + return E_FAIL; + } + + xmlnode = xmlDocGetRootElement(This->xmldoc); + return XMLElement_create((IUnknown *)This, xmlnode, (LPVOID *)&This->root); +} + +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) +{ + FIXME("(%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, +}; + HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj) { xmldoc *doc; @@ -631,6 +758,7 @@ HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj) doc->lpVtbl = &xmldoc_vtbl; doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable; + doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable; doc->ref = 1; doc->error = S_OK; doc->root = NULL;