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
);
120 HeapFree(GetProcessHeap(), 0, This
);
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 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
= HeapAlloc(GetProcessHeap(), 0, 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");