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_IDispatch) ||
86 IsEqualGUID(riid, &IID_IXMLDocument))
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));
102 IXMLDocument_AddRef(iface);
107 static ULONG WINAPI xmldoc_AddRef(IXMLDocument *iface)
109 xmldoc *This = impl_from_IXMLDocument(iface);
110 ULONG ref = InterlockedIncrement(&This->ref);
111 TRACE("(%p)->(%d)\n", This, ref);
115 static ULONG WINAPI xmldoc_Release(IXMLDocument *iface)
117 xmldoc *This = impl_from_IXMLDocument(iface);
118 LONG ref = InterlockedDecrement(&This->ref);
120 TRACE("(%p)->(%d)\n", This, ref);
124 xmlFreeDoc(This->xmldoc);
125 if (This->stream) IStream_Release(This->stream);
132 static HRESULT WINAPI xmldoc_GetTypeInfoCount(IXMLDocument *iface, UINT* pctinfo)
134 xmldoc *This = impl_from_IXMLDocument(iface);
136 TRACE("(%p)->(%p)\n", This, pctinfo);
143 static HRESULT WINAPI xmldoc_GetTypeInfo(IXMLDocument *iface, UINT iTInfo,
144 LCID lcid, ITypeInfo** ti)
146 xmldoc *This = impl_from_IXMLDocument(iface);
149 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ti);
151 hr = get_typeinfo(IXMLDocument_tid, ti);
152 ITypeInfo_AddRef(*ti);
156 static HRESULT WINAPI xmldoc_GetIDsOfNames(IXMLDocument *iface, REFIID riid,
157 LPOLESTR* rgszNames, UINT cNames,
158 LCID lcid, DISPID* rgDispId)
160 xmldoc *This = impl_from_IXMLDocument(iface);
164 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
167 if(!rgszNames || cNames == 0 || !rgDispId)
170 hr = get_typeinfo(IXMLDocument_tid, &typeinfo);
172 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
177 static HRESULT WINAPI xmldoc_Invoke(IXMLDocument *iface, DISPID dispIdMember,
178 REFIID riid, LCID lcid, WORD wFlags,
179 DISPPARAMS* pDispParams, VARIANT* pVarResult,
180 EXCEPINFO* pExcepInfo, UINT* puArgErr)
182 xmldoc *This = impl_from_IXMLDocument(iface);
186 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
187 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
189 hr = get_typeinfo(IXMLDocument_tid, &typeinfo);
191 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDocument_iface, dispIdMember, wFlags,
192 pDispParams, pVarResult, pExcepInfo, puArgErr);
197 static HRESULT WINAPI xmldoc_get_root(IXMLDocument *iface, IXMLElement **p)
199 xmldoc *This = impl_from_IXMLDocument(iface);
202 TRACE("(%p, %p)\n", iface, p);
209 if (!(root = xmlDocGetRootElement(This->xmldoc)))
212 return XMLElement_create((IUnknown *)This, root, (LPVOID *)p, FALSE);
215 static HRESULT WINAPI xmldoc_get_fileSize(IXMLDocument *iface, BSTR *p)
217 FIXME("(%p, %p): stub\n", iface, p);
221 static HRESULT WINAPI xmldoc_put_fileModifiedDate(IXMLDocument *iface, BSTR *p)
223 FIXME("(%p, %p): stub\n", iface, p);
227 static HRESULT WINAPI xmldoc_get_fileUpdatedDate(IXMLDocument *iface, BSTR *p)
229 FIXME("(%p, %p): stub\n", iface, p);
233 static HRESULT WINAPI xmldoc_get_URL(IXMLDocument *iface, BSTR *p)
235 FIXME("(%p, %p): stub\n", iface, p);
240 IBindStatusCallback IBindStatusCallback_iface;
243 static HRESULT WINAPI bsc_QueryInterface(
244 IBindStatusCallback *iface,
248 if (IsEqualGUID(riid, &IID_IUnknown) ||
249 IsEqualGUID(riid, &IID_IBindStatusCallback))
251 IBindStatusCallback_AddRef( iface );
256 TRACE("interface %s not implemented\n", debugstr_guid(riid));
257 return E_NOINTERFACE;
260 static ULONG WINAPI bsc_AddRef(
261 IBindStatusCallback *iface )
266 static ULONG WINAPI bsc_Release(
267 IBindStatusCallback *iface )
272 static HRESULT WINAPI bsc_OnStartBinding(
273 IBindStatusCallback* iface,
280 static HRESULT WINAPI bsc_GetPriority(
281 IBindStatusCallback* iface,
287 static HRESULT WINAPI bsc_OnLowResource(
288 IBindStatusCallback* iface,
294 static HRESULT WINAPI bsc_OnProgress(
295 IBindStatusCallback* iface,
299 LPCWSTR szStatusText)
304 static HRESULT WINAPI bsc_OnStopBinding(
305 IBindStatusCallback* iface,
312 static HRESULT WINAPI bsc_GetBindInfo(
313 IBindStatusCallback* iface,
317 *grfBINDF = BINDF_RESYNCHRONIZE;
322 static HRESULT WINAPI bsc_OnDataAvailable(
323 IBindStatusCallback* iface,
326 FORMATETC* pformatetc,
332 static HRESULT WINAPI bsc_OnObjectAvailable(
333 IBindStatusCallback* iface,
340 static const struct IBindStatusCallbackVtbl bsc_vtbl =
352 bsc_OnObjectAvailable
355 static bsc xmldoc_bsc = { { &bsc_vtbl } };
357 static HRESULT WINAPI xmldoc_put_URL(IXMLDocument *iface, BSTR p)
359 WCHAR url[INTERNET_MAX_URL_LENGTH];
363 IPersistStreamInit *persist;
366 TRACE("(%p, %s)\n", iface, debugstr_w(p));
373 WCHAR fullpath[MAX_PATH];
374 DWORD needed = sizeof(url) / sizeof(WCHAR);
376 if (!PathSearchAndQualifyW(p, fullpath, sizeof(fullpath) / sizeof(WCHAR)))
378 ERR("can't find path\n");
382 if (FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0)))
384 ERR("can't create url from path\n");
391 hr = CreateURLMoniker(NULL, p, &moniker);
395 CreateAsyncBindCtx(0, &xmldoc_bsc.IBindStatusCallback_iface, 0, &bctx);
397 hr = IMoniker_BindToStorage(moniker, bctx, NULL, &IID_IStream, (LPVOID *)&stream);
398 IBindCtx_Release(bctx);
399 IMoniker_Release(moniker);
403 hr = IXMLDocument_QueryInterface(iface, &IID_IPersistStreamInit, (LPVOID *)&persist);
406 IStream_Release(stream);
410 hr = IPersistStreamInit_Load(persist, stream);
411 IPersistStreamInit_Release(persist);
412 IStream_Release(stream);
417 static HRESULT WINAPI xmldoc_get_mimeType(IXMLDocument *iface, BSTR *p)
419 FIXME("(%p, %p): stub\n", iface, p);
423 static HRESULT WINAPI xmldoc_get_readyState(IXMLDocument *iface, LONG *p)
425 FIXME("(%p, %p): stub\n", iface, p);
429 static HRESULT WINAPI xmldoc_get_charset(IXMLDocument *iface, BSTR *p)
431 FIXME("(%p, %p): stub\n", iface, p);
435 static HRESULT WINAPI xmldoc_put_charset(IXMLDocument *iface, BSTR p)
437 FIXME("(%p, %p): stub\n", iface, p);
441 static HRESULT WINAPI xmldoc_get_version(IXMLDocument *iface, BSTR *p)
443 xmldoc *This = impl_from_IXMLDocument(iface);
445 TRACE("(%p, %p)\n", This, p);
447 if (!p) return E_INVALIDARG;
448 *p = bstr_from_xmlChar(This->xmldoc->version);
453 static HRESULT WINAPI xmldoc_get_doctype(IXMLDocument *iface, BSTR *p)
455 xmldoc *This = impl_from_IXMLDocument(iface);
458 TRACE("(%p, %p)\n", This, p);
460 if (!p) return E_INVALIDARG;
462 dtd = xmlGetIntSubset(This->xmldoc);
463 if (!dtd) return S_FALSE;
465 *p = bstr_from_xmlChar(dtd->name);
466 CharUpperBuffW(*p, SysStringLen(*p));
471 static HRESULT WINAPI xmldoc_get_dtdURl(IXMLDocument *iface, BSTR *p)
473 FIXME("(%p, %p): stub\n", iface, p);
477 static xmlElementType type_msxml_to_libxml(LONG type)
481 case XMLELEMTYPE_ELEMENT:
482 return XML_ELEMENT_NODE;
483 case XMLELEMTYPE_TEXT:
484 return XML_TEXT_NODE;
485 case XMLELEMTYPE_COMMENT:
486 return XML_COMMENT_NODE;
487 case XMLELEMTYPE_DOCUMENT:
488 return XML_DOCUMENT_NODE;
489 case XMLELEMTYPE_DTD:
497 return -1; /* FIXME: what is OTHER in msxml? */
500 static HRESULT WINAPI xmldoc_createElement(IXMLDocument *iface, VARIANT vType,
501 VARIANT var1, IXMLElement **ppElem)
504 static const xmlChar empty[] = "\0";
506 TRACE("(%p)->(%s %s %p)\n", iface, debugstr_variant(&vType),
507 debugstr_variant(&var1), ppElem);
514 if (V_VT(&vType) != VT_I4)
517 if(type_msxml_to_libxml(V_I4(&vType)) == -1)
520 node = xmlNewNode(NULL, empty);
521 node->type = type_msxml_to_libxml(V_I4(&vType));
523 /* FIXME: create xmlNodePtr based on vType and var1 */
524 return XMLElement_create((IUnknown *)iface, node, (LPVOID *)ppElem, TRUE);
527 static const struct IXMLDocumentVtbl xmldoc_vtbl =
529 xmldoc_QueryInterface,
532 xmldoc_GetTypeInfoCount,
534 xmldoc_GetIDsOfNames,
538 xmldoc_put_fileModifiedDate,
539 xmldoc_get_fileUpdatedDate,
543 xmldoc_get_readyState,
552 /************************************************************************
553 * xmldoc implementation of IPersistStreamInit.
555 static HRESULT WINAPI xmldoc_IPersistStreamInit_QueryInterface(
556 IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj)
558 xmldoc *this = impl_from_IPersistStreamInit(iface);
559 return IXMLDocument_QueryInterface(&this->IXMLDocument_iface, riid, ppvObj);
562 static ULONG WINAPI xmldoc_IPersistStreamInit_AddRef(
563 IPersistStreamInit *iface)
565 xmldoc *this = impl_from_IPersistStreamInit(iface);
566 return IXMLDocument_AddRef(&this->IXMLDocument_iface);
569 static ULONG WINAPI xmldoc_IPersistStreamInit_Release(
570 IPersistStreamInit *iface)
572 xmldoc *this = impl_from_IPersistStreamInit(iface);
573 return IXMLDocument_Release(&this->IXMLDocument_iface);
576 static HRESULT WINAPI xmldoc_IPersistStreamInit_GetClassID(
577 IPersistStreamInit *iface, CLSID *classid)
579 xmldoc *this = impl_from_IPersistStreamInit(iface);
580 TRACE("(%p,%p)\n", this, classid);
582 if (!classid) return E_POINTER;
584 *classid = CLSID_XMLDocument;
588 static HRESULT WINAPI xmldoc_IPersistStreamInit_IsDirty(
589 IPersistStreamInit *iface)
591 FIXME("(%p): stub!\n", iface);
595 static xmlDocPtr parse_xml(char *ptr, int len)
597 #ifdef HAVE_XMLREADMEMORY
598 return xmlReadMemory(ptr, len, NULL, NULL,
599 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS);
601 return xmlParseMemory(ptr, len);
605 static HRESULT WINAPI xmldoc_IPersistStreamInit_Load(
606 IPersistStreamInit *iface, LPSTREAM pStm)
608 xmldoc *This = impl_from_IPersistStreamInit(iface);
611 DWORD read, written, len;
615 TRACE("(%p, %p)\n", iface, pStm);
620 /* release previously allocated stream */
621 if (This->stream) IStream_Release(This->stream);
622 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
628 IStream_Read(pStm, buf, sizeof(buf), &read);
629 hr = IStream_Write(This->stream, buf, read, &written);
630 } while(SUCCEEDED(hr) && written != 0 && read != 0);
634 ERR("Failed to copy stream\n");
638 hr = GetHGlobalFromStream(This->stream, &hglobal);
642 len = GlobalSize(hglobal);
643 ptr = GlobalLock(hglobal);
646 xmlFreeDoc(This->xmldoc);
647 This->xmldoc = parse_xml(ptr, len);
649 GlobalUnlock(hglobal);
653 ERR("Failed to parse xml\n");
660 static HRESULT WINAPI xmldoc_IPersistStreamInit_Save(
661 IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty)
663 FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty);
667 static HRESULT WINAPI xmldoc_IPersistStreamInit_GetSizeMax(
668 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
670 xmldoc *This = impl_from_IPersistStreamInit(iface);
671 TRACE("(%p, %p)\n", This, pcbSize);
675 static HRESULT WINAPI xmldoc_IPersistStreamInit_InitNew(
676 IPersistStreamInit *iface)
678 xmldoc *This = impl_from_IPersistStreamInit(iface);
679 TRACE("(%p)\n", This);
683 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
685 xmldoc_IPersistStreamInit_QueryInterface,
686 xmldoc_IPersistStreamInit_AddRef,
687 xmldoc_IPersistStreamInit_Release,
688 xmldoc_IPersistStreamInit_GetClassID,
689 xmldoc_IPersistStreamInit_IsDirty,
690 xmldoc_IPersistStreamInit_Load,
691 xmldoc_IPersistStreamInit_Save,
692 xmldoc_IPersistStreamInit_GetSizeMax,
693 xmldoc_IPersistStreamInit_InitNew
696 HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
700 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
702 doc = heap_alloc(sizeof (*doc));
704 return E_OUTOFMEMORY;
706 doc->IXMLDocument_iface.lpVtbl = &xmldoc_vtbl;
707 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
713 *ppObj = &doc->IXMLDocument_iface;
715 TRACE("returning iface %p\n", *ppObj);
721 HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
723 MESSAGE("This program tried to use an XMLDocument object, but\n"
724 "libxml2 support was not present at compile time.\n");