2 * XML Document implementation
4 * Copyright 2007 James Hawkins
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
41 #include "wine/debug.h"
43 #include "msxml_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
49 /* FIXME: IXMLDocument needs to implement
54 typedef struct _xmldoc
56 IXMLDocument IXMLDocument_iface;
57 IPersistStreamInit IPersistStreamInit_iface;
68 static inline xmldoc *impl_from_IXMLDocument(IXMLDocument *iface)
70 return CONTAINING_RECORD(iface, xmldoc, IXMLDocument_iface);
73 static inline xmldoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
75 return CONTAINING_RECORD(iface, xmldoc, IPersistStreamInit_iface);
78 static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, void** ppvObject)
80 xmldoc *This = impl_from_IXMLDocument(iface);
82 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
84 if (IsEqualGUID(riid, &IID_IUnknown) ||
85 IsEqualGUID(riid, &IID_IXMLDocument) ||
86 IsEqualGUID(riid, &IID_IXMLDOMDocument))
90 else if (IsEqualGUID(&IID_IPersistStreamInit, riid) ||
91 IsEqualGUID(&IID_IPersistStream, riid))
93 *ppvObject = &This->IPersistStreamInit_iface;
97 FIXME("interface %s not implemented\n", debugstr_guid(riid));
101 IXMLDocument_AddRef(iface);
106 static ULONG WINAPI xmldoc_AddRef(IXMLDocument *iface)
108 xmldoc *This = impl_from_IXMLDocument(iface);
110 return InterlockedIncrement(&This->ref);
113 static ULONG WINAPI xmldoc_Release(IXMLDocument *iface)
115 xmldoc *This = impl_from_IXMLDocument(iface);
120 ref = InterlockedDecrement(&This->ref);
123 xmlFreeDoc(This->xmldoc);
124 if (This->stream) IStream_Release(This->stream);
131 static HRESULT WINAPI xmldoc_GetTypeInfoCount(IXMLDocument *iface, UINT* pctinfo)
133 xmldoc *This = impl_from_IXMLDocument(iface);
135 TRACE("(%p)->(%p)\n", This, pctinfo);
142 static HRESULT WINAPI xmldoc_GetTypeInfo(IXMLDocument *iface, UINT iTInfo,
143 LCID lcid, ITypeInfo** ppTInfo)
145 xmldoc *This = impl_from_IXMLDocument(iface);
148 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
150 hr = get_typeinfo(IXMLDocument_tid, ppTInfo);
155 static HRESULT WINAPI xmldoc_GetIDsOfNames(IXMLDocument *iface, REFIID riid,
156 LPOLESTR* rgszNames, UINT cNames,
157 LCID lcid, DISPID* rgDispId)
159 xmldoc *This = impl_from_IXMLDocument(iface);
163 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
166 if(!rgszNames || cNames == 0 || !rgDispId)
169 hr = get_typeinfo(IXMLDocument_tid, &typeinfo);
172 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
173 ITypeInfo_Release(typeinfo);
179 static HRESULT WINAPI xmldoc_Invoke(IXMLDocument *iface, DISPID dispIdMember,
180 REFIID riid, LCID lcid, WORD wFlags,
181 DISPPARAMS* pDispParams, VARIANT* pVarResult,
182 EXCEPINFO* pExcepInfo, UINT* puArgErr)
184 xmldoc *This = impl_from_IXMLDocument(iface);
188 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
189 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
191 hr = get_typeinfo(IXMLDocument_tid, &typeinfo);
194 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDocument_iface, dispIdMember, wFlags,
195 pDispParams, pVarResult, pExcepInfo, puArgErr);
196 ITypeInfo_Release(typeinfo);
202 static HRESULT WINAPI xmldoc_get_root(IXMLDocument *iface, IXMLElement **p)
204 xmldoc *This = impl_from_IXMLDocument(iface);
207 TRACE("(%p, %p)\n", iface, p);
214 if (!(root = xmlDocGetRootElement(This->xmldoc)))
217 return XMLElement_create((IUnknown *)This, root, (LPVOID *)p, FALSE);
220 static HRESULT WINAPI xmldoc_get_fileSize(IXMLDocument *iface, BSTR *p)
222 FIXME("(%p, %p): stub\n", iface, p);
226 static HRESULT WINAPI xmldoc_put_fileModifiedDate(IXMLDocument *iface, BSTR *p)
228 FIXME("(%p, %p): stub\n", iface, p);
232 static HRESULT WINAPI xmldoc_get_fileUpdatedDate(IXMLDocument *iface, BSTR *p)
234 FIXME("(%p, %p): stub\n", iface, p);
238 static HRESULT WINAPI xmldoc_get_URL(IXMLDocument *iface, BSTR *p)
240 FIXME("(%p, %p): stub\n", iface, p);
245 IBindStatusCallback IBindStatusCallback_iface;
248 static HRESULT WINAPI bsc_QueryInterface(
249 IBindStatusCallback *iface,
253 if (IsEqualGUID(riid, &IID_IUnknown) ||
254 IsEqualGUID(riid, &IID_IBindStatusCallback))
256 IBindStatusCallback_AddRef( iface );
261 TRACE("interface %s not implemented\n", debugstr_guid(riid));
262 return E_NOINTERFACE;
265 static ULONG WINAPI bsc_AddRef(
266 IBindStatusCallback *iface )
271 static ULONG WINAPI bsc_Release(
272 IBindStatusCallback *iface )
277 static HRESULT WINAPI bsc_OnStartBinding(
278 IBindStatusCallback* iface,
285 static HRESULT WINAPI bsc_GetPriority(
286 IBindStatusCallback* iface,
292 static HRESULT WINAPI bsc_OnLowResource(
293 IBindStatusCallback* iface,
299 static HRESULT WINAPI bsc_OnProgress(
300 IBindStatusCallback* iface,
304 LPCWSTR szStatusText)
309 static HRESULT WINAPI bsc_OnStopBinding(
310 IBindStatusCallback* iface,
317 static HRESULT WINAPI bsc_GetBindInfo(
318 IBindStatusCallback* iface,
322 *grfBINDF = BINDF_RESYNCHRONIZE;
327 static HRESULT WINAPI bsc_OnDataAvailable(
328 IBindStatusCallback* iface,
331 FORMATETC* pformatetc,
337 static HRESULT WINAPI bsc_OnObjectAvailable(
338 IBindStatusCallback* iface,
345 static const struct IBindStatusCallbackVtbl bsc_vtbl =
357 bsc_OnObjectAvailable
360 static bsc xmldoc_bsc = { { &bsc_vtbl } };
362 static HRESULT WINAPI xmldoc_put_URL(IXMLDocument *iface, BSTR p)
364 WCHAR url[INTERNET_MAX_URL_LENGTH];
368 IPersistStreamInit *persist;
371 TRACE("(%p, %s)\n", iface, debugstr_w(p));
378 WCHAR fullpath[MAX_PATH];
379 DWORD needed = sizeof(url) / sizeof(WCHAR);
381 if (!PathSearchAndQualifyW(p, fullpath, sizeof(fullpath) / sizeof(WCHAR)))
383 ERR("can't find path\n");
387 if (FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0)))
389 ERR("can't create url from path\n");
396 hr = CreateURLMoniker(NULL, p, &moniker);
400 CreateAsyncBindCtx(0, &xmldoc_bsc.IBindStatusCallback_iface, 0, &bctx);
402 hr = IMoniker_BindToStorage(moniker, bctx, NULL, &IID_IStream, (LPVOID *)&stream);
403 IBindCtx_Release(bctx);
404 IMoniker_Release(moniker);
408 hr = IXMLDocument_QueryInterface(iface, &IID_IPersistStreamInit, (LPVOID *)&persist);
411 IStream_Release(stream);
415 hr = IPersistStreamInit_Load(persist, stream);
416 IPersistStreamInit_Release(persist);
417 IStream_Release(stream);
422 static HRESULT WINAPI xmldoc_get_mimeType(IXMLDocument *iface, BSTR *p)
424 FIXME("(%p, %p): stub\n", iface, p);
428 static HRESULT WINAPI xmldoc_get_readyState(IXMLDocument *iface, LONG *p)
430 FIXME("(%p, %p): stub\n", iface, p);
434 static HRESULT WINAPI xmldoc_get_charset(IXMLDocument *iface, BSTR *p)
436 FIXME("(%p, %p): stub\n", iface, p);
440 static HRESULT WINAPI xmldoc_put_charset(IXMLDocument *iface, BSTR p)
442 FIXME("(%p, %p): stub\n", iface, p);
446 static HRESULT WINAPI xmldoc_get_version(IXMLDocument *iface, BSTR *p)
448 xmldoc *This = impl_from_IXMLDocument(iface);
450 TRACE("(%p, %p)\n", This, p);
452 if (!p) return E_INVALIDARG;
453 *p = bstr_from_xmlChar(This->xmldoc->version);
458 static HRESULT WINAPI xmldoc_get_doctype(IXMLDocument *iface, BSTR *p)
460 xmldoc *This = impl_from_IXMLDocument(iface);
463 TRACE("(%p, %p)\n", This, p);
465 if (!p) return E_INVALIDARG;
467 dtd = xmlGetIntSubset(This->xmldoc);
468 if (!dtd) return S_FALSE;
470 *p = bstr_from_xmlChar(dtd->name);
471 CharUpperBuffW(*p, SysStringLen(*p));
476 static HRESULT WINAPI xmldoc_get_dtdURl(IXMLDocument *iface, BSTR *p)
478 FIXME("(%p, %p): stub\n", iface, p);
482 static xmlElementType type_msxml_to_libxml(LONG type)
486 case XMLELEMTYPE_ELEMENT:
487 return XML_ELEMENT_NODE;
488 case XMLELEMTYPE_TEXT:
489 return XML_TEXT_NODE;
490 case XMLELEMTYPE_COMMENT:
491 return XML_COMMENT_NODE;
492 case XMLELEMTYPE_DOCUMENT:
493 return XML_DOCUMENT_NODE;
494 case XMLELEMTYPE_DTD:
502 return -1; /* FIXME: what is OTHER in msxml? */
505 static HRESULT WINAPI xmldoc_createElement(IXMLDocument *iface, VARIANT vType,
506 VARIANT var1, IXMLElement **ppElem)
509 static const xmlChar empty[] = "\0";
511 TRACE("(%p)->(%s %s %p)\n", iface, debugstr_variant(&vType),
512 debugstr_variant(&var1), ppElem);
519 if (V_VT(&vType) != VT_I4)
522 if(type_msxml_to_libxml(V_I4(&vType)) == -1)
525 node = xmlNewNode(NULL, empty);
526 node->type = type_msxml_to_libxml(V_I4(&vType));
528 /* FIXME: create xmlNodePtr based on vType and var1 */
529 return XMLElement_create((IUnknown *)iface, node, (LPVOID *)ppElem, TRUE);
532 static const struct IXMLDocumentVtbl xmldoc_vtbl =
534 xmldoc_QueryInterface,
537 xmldoc_GetTypeInfoCount,
539 xmldoc_GetIDsOfNames,
543 xmldoc_put_fileModifiedDate,
544 xmldoc_get_fileUpdatedDate,
548 xmldoc_get_readyState,
557 /************************************************************************
558 * xmldoc implementation of IPersistStreamInit.
560 static HRESULT WINAPI xmldoc_IPersistStreamInit_QueryInterface(
561 IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj)
563 xmldoc *this = impl_from_IPersistStreamInit(iface);
564 return IXMLDocument_QueryInterface(&this->IXMLDocument_iface, riid, ppvObj);
567 static ULONG WINAPI xmldoc_IPersistStreamInit_AddRef(
568 IPersistStreamInit *iface)
570 xmldoc *this = impl_from_IPersistStreamInit(iface);
571 return IXMLDocument_AddRef(&this->IXMLDocument_iface);
574 static ULONG WINAPI xmldoc_IPersistStreamInit_Release(
575 IPersistStreamInit *iface)
577 xmldoc *this = impl_from_IPersistStreamInit(iface);
578 return IXMLDocument_Release(&this->IXMLDocument_iface);
581 static HRESULT WINAPI xmldoc_IPersistStreamInit_GetClassID(
582 IPersistStreamInit *iface, CLSID *classid)
584 xmldoc *this = impl_from_IPersistStreamInit(iface);
585 TRACE("(%p,%p)\n", this, classid);
587 if (!classid) return E_POINTER;
589 *classid = CLSID_XMLDocument;
593 static HRESULT WINAPI xmldoc_IPersistStreamInit_IsDirty(
594 IPersistStreamInit *iface)
596 FIXME("(%p): stub!\n", iface);
600 static xmlDocPtr parse_xml(char *ptr, int len)
602 #ifdef HAVE_XMLREADMEMORY
603 return xmlReadMemory(ptr, len, NULL, NULL,
604 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS);
606 return xmlParseMemory(ptr, len);
610 static HRESULT WINAPI xmldoc_IPersistStreamInit_Load(
611 IPersistStreamInit *iface, LPSTREAM pStm)
613 xmldoc *This = impl_from_IPersistStreamInit(iface);
616 DWORD read, written, len;
620 TRACE("(%p, %p)\n", iface, pStm);
625 /* release previously allocated stream */
626 if (This->stream) IStream_Release(This->stream);
627 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
633 IStream_Read(pStm, buf, sizeof(buf), &read);
634 hr = IStream_Write(This->stream, buf, read, &written);
635 } while(SUCCEEDED(hr) && written != 0 && read != 0);
639 ERR("Failed to copy stream\n");
643 hr = GetHGlobalFromStream(This->stream, &hglobal);
647 len = GlobalSize(hglobal);
648 ptr = GlobalLock(hglobal);
651 xmlFreeDoc(This->xmldoc);
652 This->xmldoc = parse_xml(ptr, len);
654 GlobalUnlock(hglobal);
658 ERR("Failed to parse xml\n");
665 static HRESULT WINAPI xmldoc_IPersistStreamInit_Save(
666 IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty)
668 FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty);
672 static HRESULT WINAPI xmldoc_IPersistStreamInit_GetSizeMax(
673 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
675 xmldoc *This = impl_from_IPersistStreamInit(iface);
676 TRACE("(%p, %p)\n", This, pcbSize);
680 static HRESULT WINAPI xmldoc_IPersistStreamInit_InitNew(
681 IPersistStreamInit *iface)
683 xmldoc *This = impl_from_IPersistStreamInit(iface);
684 TRACE("(%p)\n", This);
688 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
690 xmldoc_IPersistStreamInit_QueryInterface,
691 xmldoc_IPersistStreamInit_AddRef,
692 xmldoc_IPersistStreamInit_Release,
693 xmldoc_IPersistStreamInit_GetClassID,
694 xmldoc_IPersistStreamInit_IsDirty,
695 xmldoc_IPersistStreamInit_Load,
696 xmldoc_IPersistStreamInit_Save,
697 xmldoc_IPersistStreamInit_GetSizeMax,
698 xmldoc_IPersistStreamInit_InitNew
701 HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
705 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
707 doc = heap_alloc(sizeof (*doc));
709 return E_OUTOFMEMORY;
711 doc->IXMLDocument_iface.lpVtbl = &xmldoc_vtbl;
712 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
718 *ppObj = &doc->IXMLDocument_iface;
720 TRACE("returning iface %p\n", *ppObj);
726 HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
728 MESSAGE("This program tried to use an XMLDocument object, but\n"
729 "libxml2 support was not present at compile time.\n");