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
36 #include "wine/debug.h"
38 #include "msxml_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
44 /* FIXME: IXMLDocument needs to implement
49 typedef struct _xmldoc
51 const IXMLDocumentVtbl *lpVtbl;
52 const IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
63 static inline xmldoc *impl_from_IXMLDocument(IXMLDocument *iface)
65 return (xmldoc *)((char*)iface - FIELD_OFFSET(xmldoc, lpVtbl));
68 static inline xmldoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
70 return (xmldoc *)((char*)iface - FIELD_OFFSET(xmldoc, lpvtblIPersistStreamInit));
73 static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, void** ppvObject)
75 xmldoc *This = impl_from_IXMLDocument(iface);
77 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
79 if (IsEqualGUID(riid, &IID_IUnknown) ||
80 IsEqualGUID(riid, &IID_IXMLDocument) ||
81 IsEqualGUID(riid, &IID_IXMLDOMDocument))
85 else if (IsEqualGUID(&IID_IPersistStreamInit, riid) ||
86 IsEqualGUID(&IID_IPersistStream, riid))
88 *ppvObject = &(This->lpvtblIPersistStreamInit);
92 FIXME("interface %s not implemented\n", debugstr_guid(riid));
96 IXMLDocument_AddRef(iface);
101 static ULONG WINAPI xmldoc_AddRef(IXMLDocument *iface)
103 xmldoc *This = impl_from_IXMLDocument(iface);
105 return InterlockedIncrement(&This->ref);
108 static ULONG WINAPI xmldoc_Release(IXMLDocument *iface)
110 xmldoc *This = impl_from_IXMLDocument(iface);
115 ref = InterlockedDecrement(&This->ref);
118 xmlFreeDoc(This->xmldoc);
119 if (This->stream) IStream_Release(This->stream);
126 static HRESULT WINAPI xmldoc_GetTypeInfoCount(IXMLDocument *iface, UINT* pctinfo)
128 xmldoc *This = impl_from_IXMLDocument(iface);
130 TRACE("(%p)->(%p)\n", This, pctinfo);
137 static HRESULT WINAPI xmldoc_GetTypeInfo(IXMLDocument *iface, UINT iTInfo,
138 LCID lcid, ITypeInfo** ppTInfo)
140 xmldoc *This = impl_from_IXMLDocument(iface);
143 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
145 hr = get_typeinfo(IXMLDocument_tid, ppTInfo);
150 static HRESULT WINAPI xmldoc_GetIDsOfNames(IXMLDocument *iface, REFIID riid,
151 LPOLESTR* rgszNames, UINT cNames,
152 LCID lcid, DISPID* rgDispId)
154 xmldoc *This = impl_from_IXMLDocument(iface);
158 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
161 if(!rgszNames || cNames == 0 || !rgDispId)
164 hr = get_typeinfo(IXMLDocument_tid, &typeinfo);
167 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
168 ITypeInfo_Release(typeinfo);
174 static HRESULT WINAPI xmldoc_Invoke(IXMLDocument *iface, DISPID dispIdMember,
175 REFIID riid, LCID lcid, WORD wFlags,
176 DISPPARAMS* pDispParams, VARIANT* pVarResult,
177 EXCEPINFO* pExcepInfo, UINT* puArgErr)
179 xmldoc *This = impl_from_IXMLDocument(iface);
183 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
184 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
186 hr = get_typeinfo(IXMLDocument_tid, &typeinfo);
189 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
190 pVarResult, pExcepInfo, puArgErr);
191 ITypeInfo_Release(typeinfo);
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 const struct IBindStatusCallbackVtbl *lpVtbl;
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 FIXME("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, (IBindStatusCallback *)&xmldoc_bsc, 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, %p)\n", iface, ppElem);
513 if (V_VT(&vType) != VT_I4)
516 if(type_msxml_to_libxml(V_I4(&vType)) == -1)
519 node = xmlNewNode(NULL, empty);
520 node->type = type_msxml_to_libxml(V_I4(&vType));
522 /* FIXME: create xmlNodePtr based on vType and var1 */
523 return XMLElement_create((IUnknown *)iface, node, (LPVOID *)ppElem, TRUE);
526 static const struct IXMLDocumentVtbl xmldoc_vtbl =
528 xmldoc_QueryInterface,
531 xmldoc_GetTypeInfoCount,
533 xmldoc_GetIDsOfNames,
537 xmldoc_put_fileModifiedDate,
538 xmldoc_get_fileUpdatedDate,
542 xmldoc_get_readyState,
551 /************************************************************************
552 * xmldoc implementation of IPersistStreamInit.
554 static HRESULT WINAPI xmldoc_IPersistStreamInit_QueryInterface(
555 IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj)
557 xmldoc *this = impl_from_IPersistStreamInit(iface);
558 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
561 static ULONG WINAPI xmldoc_IPersistStreamInit_AddRef(
562 IPersistStreamInit *iface)
564 xmldoc *this = impl_from_IPersistStreamInit(iface);
565 return IXMLDocument_AddRef((IXMLDocument *)this);
568 static ULONG WINAPI xmldoc_IPersistStreamInit_Release(
569 IPersistStreamInit *iface)
571 xmldoc *this = impl_from_IPersistStreamInit(iface);
572 return IXMLDocument_Release((IXMLDocument *)this);
575 static HRESULT WINAPI xmldoc_IPersistStreamInit_GetClassID(
576 IPersistStreamInit *iface, CLSID *classid)
578 xmldoc *this = impl_from_IPersistStreamInit(iface);
579 TRACE("(%p,%p)\n", this, classid);
581 if (!classid) return E_POINTER;
583 *classid = CLSID_XMLDocument;
587 static HRESULT WINAPI xmldoc_IPersistStreamInit_IsDirty(
588 IPersistStreamInit *iface)
590 FIXME("(%p): stub!\n", iface);
594 static xmlDocPtr parse_xml(char *ptr, int len)
596 #ifdef HAVE_XMLREADMEMORY
597 return xmlReadMemory(ptr, len, NULL, NULL,
598 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS);
600 return xmlParseMemory(ptr, len);
604 static HRESULT WINAPI xmldoc_IPersistStreamInit_Load(
605 IPersistStreamInit *iface, LPSTREAM pStm)
607 xmldoc *This = impl_from_IPersistStreamInit(iface);
610 DWORD read, written, len;
614 TRACE("(%p, %p)\n", iface, pStm);
619 /* release previously allocated stream */
620 if (This->stream) IStream_Release(This->stream);
621 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
627 IStream_Read(pStm, buf, sizeof(buf), &read);
628 hr = IStream_Write(This->stream, buf, read, &written);
629 } while(SUCCEEDED(hr) && written != 0 && read != 0);
633 ERR("Failed to copy stream\n");
637 hr = GetHGlobalFromStream(This->stream, &hglobal);
641 len = GlobalSize(hglobal);
642 ptr = GlobalLock(hglobal);
645 xmlFreeDoc(This->xmldoc);
646 This->xmldoc = parse_xml(ptr, len);
648 GlobalUnlock(hglobal);
652 ERR("Failed to parse xml\n");
659 static HRESULT WINAPI xmldoc_IPersistStreamInit_Save(
660 IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty)
662 FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty);
666 static HRESULT WINAPI xmldoc_IPersistStreamInit_GetSizeMax(
667 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
669 xmldoc *This = impl_from_IPersistStreamInit(iface);
670 TRACE("(%p, %p)\n", This, pcbSize);
674 static HRESULT WINAPI xmldoc_IPersistStreamInit_InitNew(
675 IPersistStreamInit *iface)
677 xmldoc *This = impl_from_IPersistStreamInit(iface);
678 TRACE("(%p)\n", This);
682 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
684 xmldoc_IPersistStreamInit_QueryInterface,
685 xmldoc_IPersistStreamInit_AddRef,
686 xmldoc_IPersistStreamInit_Release,
687 xmldoc_IPersistStreamInit_GetClassID,
688 xmldoc_IPersistStreamInit_IsDirty,
689 xmldoc_IPersistStreamInit_Load,
690 xmldoc_IPersistStreamInit_Save,
691 xmldoc_IPersistStreamInit_GetSizeMax,
692 xmldoc_IPersistStreamInit_InitNew
695 HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
699 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
701 doc = heap_alloc(sizeof (*doc));
703 return E_OUTOFMEMORY;
705 doc->lpVtbl = &xmldoc_vtbl;
706 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
712 *ppObj = &doc->lpVtbl;
714 TRACE("returning iface %p\n", *ppObj);
720 HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
722 MESSAGE("This program tried to use an XMLDocument object, but\n"
723 "libxml2 support was not present at compile time.\n");