push ac4b6ebdd3fd886d6a18959265755579ed195b88
[wine/hacks.git] / dlls / msxml3 / xmldoc.c
blobd1a010f64859b82ee6b85844329f0494f2970642
1 /*
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
21 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "msxml2.h"
31 #include "wininet.h"
32 #include "winreg.h"
33 #include "shlwapi.h"
34 #include "ocidl.h"
36 #include "wine/debug.h"
38 #include "msxml_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
42 #ifdef HAVE_LIBXML2
44 /* FIXME: IXMLDocument needs to implement
45 * - IXMLError
46 * - IPersistMoniker
49 typedef struct _xmldoc
51 const IXMLDocumentVtbl *lpVtbl;
52 const IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
53 LONG ref;
54 HRESULT error;
56 /* IXMLDocument */
57 xmlDocPtr xmldoc;
59 /* IPersistStream */
60 IStream *stream;
61 } xmldoc;
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))
83 *ppvObject = iface;
85 else if (IsEqualGUID(&IID_IPersistStreamInit, riid) ||
86 IsEqualGUID(&IID_IPersistStream, riid))
88 *ppvObject = &(This->lpvtblIPersistStreamInit);
90 else
92 FIXME("interface %s not implemented\n", debugstr_guid(riid));
93 return E_NOINTERFACE;
96 IXMLDocument_AddRef(iface);
98 return S_OK;
101 static ULONG WINAPI xmldoc_AddRef(IXMLDocument *iface)
103 xmldoc *This = impl_from_IXMLDocument(iface);
104 TRACE("%p\n", This);
105 return InterlockedIncrement(&This->ref);
108 static ULONG WINAPI xmldoc_Release(IXMLDocument *iface)
110 xmldoc *This = impl_from_IXMLDocument(iface);
111 LONG ref;
113 TRACE("%p\n", This);
115 ref = InterlockedDecrement(&This->ref);
116 if (ref == 0)
118 xmlFreeDoc(This->xmldoc);
119 if (This->stream) IStream_Release(This->stream);
120 heap_free(This);
123 return ref;
126 static HRESULT WINAPI xmldoc_GetTypeInfoCount(IXMLDocument *iface, UINT* pctinfo)
128 xmldoc *This = impl_from_IXMLDocument(iface);
130 TRACE("(%p)->(%p)\n", This, pctinfo);
132 *pctinfo = 1;
134 return S_OK;
137 static HRESULT WINAPI xmldoc_GetTypeInfo(IXMLDocument *iface, UINT iTInfo,
138 LCID lcid, ITypeInfo** ppTInfo)
140 xmldoc *This = impl_from_IXMLDocument(iface);
141 HRESULT hr;
143 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
145 hr = get_typeinfo(IXMLDocument_tid, ppTInfo);
147 return hr;
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);
155 ITypeInfo *typeinfo;
156 HRESULT hr;
158 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
159 lcid, rgDispId);
161 if(!rgszNames || cNames == 0 || !rgDispId)
162 return E_INVALIDARG;
164 hr = get_typeinfo(IXMLDocument_tid, &typeinfo);
165 if(SUCCEEDED(hr))
167 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
168 ITypeInfo_Release(typeinfo);
171 return hr;
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);
180 ITypeInfo *typeinfo;
181 HRESULT hr;
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);
187 if(SUCCEEDED(hr))
189 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
190 pVarResult, pExcepInfo, puArgErr);
191 ITypeInfo_Release(typeinfo);
194 return hr;
197 static HRESULT WINAPI xmldoc_get_root(IXMLDocument *iface, IXMLElement **p)
199 xmldoc *This = impl_from_IXMLDocument(iface);
200 xmlNodePtr root;
202 TRACE("(%p, %p)\n", iface, p);
204 if (!p)
205 return E_INVALIDARG;
207 *p = NULL;
209 if (!(root = xmlDocGetRootElement(This->xmldoc)))
210 return E_FAIL;
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);
218 return E_NOTIMPL;
221 static HRESULT WINAPI xmldoc_put_fileModifiedDate(IXMLDocument *iface, BSTR *p)
223 FIXME("(%p, %p): stub\n", iface, p);
224 return E_NOTIMPL;
227 static HRESULT WINAPI xmldoc_get_fileUpdatedDate(IXMLDocument *iface, BSTR *p)
229 FIXME("(%p, %p): stub\n", iface, p);
230 return E_NOTIMPL;
233 static HRESULT WINAPI xmldoc_get_URL(IXMLDocument *iface, BSTR *p)
235 FIXME("(%p, %p): stub\n", iface, p);
236 return E_NOTIMPL;
239 typedef struct {
240 const struct IBindStatusCallbackVtbl *lpVtbl;
241 } bsc;
243 static HRESULT WINAPI bsc_QueryInterface(
244 IBindStatusCallback *iface,
245 REFIID riid,
246 LPVOID *ppobj )
248 if (IsEqualGUID(riid, &IID_IUnknown) ||
249 IsEqualGUID(riid, &IID_IBindStatusCallback))
251 IBindStatusCallback_AddRef( iface );
252 *ppobj = iface;
253 return S_OK;
256 FIXME("interface %s not implemented\n", debugstr_guid(riid));
257 return E_NOINTERFACE;
260 static ULONG WINAPI bsc_AddRef(
261 IBindStatusCallback *iface )
263 return 2;
266 static ULONG WINAPI bsc_Release(
267 IBindStatusCallback *iface )
269 return 1;
272 static HRESULT WINAPI bsc_OnStartBinding(
273 IBindStatusCallback* iface,
274 DWORD dwReserved,
275 IBinding* pib)
277 return S_OK;
280 static HRESULT WINAPI bsc_GetPriority(
281 IBindStatusCallback* iface,
282 LONG* pnPriority)
284 return S_OK;
287 static HRESULT WINAPI bsc_OnLowResource(
288 IBindStatusCallback* iface,
289 DWORD reserved)
291 return S_OK;
294 static HRESULT WINAPI bsc_OnProgress(
295 IBindStatusCallback* iface,
296 ULONG ulProgress,
297 ULONG ulProgressMax,
298 ULONG ulStatusCode,
299 LPCWSTR szStatusText)
301 return S_OK;
304 static HRESULT WINAPI bsc_OnStopBinding(
305 IBindStatusCallback* iface,
306 HRESULT hresult,
307 LPCWSTR szError)
309 return S_OK;
312 static HRESULT WINAPI bsc_GetBindInfo(
313 IBindStatusCallback* iface,
314 DWORD* grfBINDF,
315 BINDINFO* pbindinfo)
317 *grfBINDF = BINDF_RESYNCHRONIZE;
319 return S_OK;
322 static HRESULT WINAPI bsc_OnDataAvailable(
323 IBindStatusCallback* iface,
324 DWORD grfBSCF,
325 DWORD dwSize,
326 FORMATETC* pformatetc,
327 STGMEDIUM* pstgmed)
329 return S_OK;
332 static HRESULT WINAPI bsc_OnObjectAvailable(
333 IBindStatusCallback* iface,
334 REFIID riid,
335 IUnknown* punk)
337 return S_OK;
340 static const struct IBindStatusCallbackVtbl bsc_vtbl =
342 bsc_QueryInterface,
343 bsc_AddRef,
344 bsc_Release,
345 bsc_OnStartBinding,
346 bsc_GetPriority,
347 bsc_OnLowResource,
348 bsc_OnProgress,
349 bsc_OnStopBinding,
350 bsc_GetBindInfo,
351 bsc_OnDataAvailable,
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];
360 IStream *stream;
361 IBindCtx *bctx;
362 IMoniker *moniker;
363 IPersistStreamInit *persist;
364 HRESULT hr;
366 TRACE("(%p, %s)\n", iface, debugstr_w(p));
368 if (!p)
369 return E_INVALIDARG;
371 if (!PathIsURLW(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");
379 return E_FAIL;
382 if (FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0)))
384 ERR("can't create url from path\n");
385 return E_FAIL;
388 p = url;
391 hr = CreateURLMoniker(NULL, p, &moniker);
392 if (FAILED(hr))
393 return hr;
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);
400 if (FAILED(hr))
401 return hr;
403 hr = IXMLDocument_QueryInterface(iface, &IID_IPersistStreamInit, (LPVOID *)&persist);
404 if (FAILED(hr))
406 IStream_Release(stream);
407 return hr;
410 hr = IPersistStreamInit_Load(persist, stream);
411 IPersistStreamInit_Release(persist);
412 IStream_Release(stream);
414 return hr;
417 static HRESULT WINAPI xmldoc_get_mimeType(IXMLDocument *iface, BSTR *p)
419 FIXME("(%p, %p): stub\n", iface, p);
420 return E_NOTIMPL;
423 static HRESULT WINAPI xmldoc_get_readyState(IXMLDocument *iface, LONG *p)
425 FIXME("(%p, %p): stub\n", iface, p);
426 return E_NOTIMPL;
429 static HRESULT WINAPI xmldoc_get_charset(IXMLDocument *iface, BSTR *p)
431 FIXME("(%p, %p): stub\n", iface, p);
432 return E_NOTIMPL;
435 static HRESULT WINAPI xmldoc_put_charset(IXMLDocument *iface, BSTR p)
437 FIXME("(%p, %p): stub\n", iface, p);
438 return E_NOTIMPL;
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);
450 return S_OK;
453 static HRESULT WINAPI xmldoc_get_doctype(IXMLDocument *iface, BSTR *p)
455 xmldoc *This = impl_from_IXMLDocument(iface);
456 xmlDtd *dtd;
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));
468 return S_OK;
471 static HRESULT WINAPI xmldoc_get_dtdURl(IXMLDocument *iface, BSTR *p)
473 FIXME("(%p, %p): stub\n", iface, p);
474 return E_NOTIMPL;
477 static xmlElementType type_msxml_to_libxml(LONG type)
479 switch (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:
490 return XML_DTD_NODE;
491 case XMLELEMTYPE_PI:
492 return XML_PI_NODE;
493 default:
494 break;
497 return -1; /* FIXME: what is OTHER in msxml? */
500 static HRESULT WINAPI xmldoc_createElement(IXMLDocument *iface, VARIANT vType,
501 VARIANT var1, IXMLElement **ppElem)
503 xmlNodePtr node;
504 static const xmlChar empty[] = "\0";
506 TRACE("(%p, %p)\n", iface, ppElem);
508 if (!ppElem)
509 return E_INVALIDARG;
511 *ppElem = NULL;
513 if (V_VT(&vType) != VT_I4)
514 return E_INVALIDARG;
516 if(type_msxml_to_libxml(V_I4(&vType)) == -1)
517 return E_NOTIMPL;
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,
529 xmldoc_AddRef,
530 xmldoc_Release,
531 xmldoc_GetTypeInfoCount,
532 xmldoc_GetTypeInfo,
533 xmldoc_GetIDsOfNames,
534 xmldoc_Invoke,
535 xmldoc_get_root,
536 xmldoc_get_fileSize,
537 xmldoc_put_fileModifiedDate,
538 xmldoc_get_fileUpdatedDate,
539 xmldoc_get_URL,
540 xmldoc_put_URL,
541 xmldoc_get_mimeType,
542 xmldoc_get_readyState,
543 xmldoc_get_charset,
544 xmldoc_put_charset,
545 xmldoc_get_version,
546 xmldoc_get_doctype,
547 xmldoc_get_dtdURl,
548 xmldoc_createElement
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;
584 return S_OK;
587 static HRESULT WINAPI xmldoc_IPersistStreamInit_IsDirty(
588 IPersistStreamInit *iface)
590 FIXME("(%p): stub!\n", iface);
591 return E_NOTIMPL;
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);
599 #else
600 return xmlParseMemory(ptr, len);
601 #endif
604 static HRESULT WINAPI xmldoc_IPersistStreamInit_Load(
605 IPersistStreamInit *iface, LPSTREAM pStm)
607 xmldoc *This = impl_from_IPersistStreamInit(iface);
608 HRESULT hr;
609 HGLOBAL hglobal;
610 DWORD read, written, len;
611 BYTE buf[4096];
612 char *ptr;
614 TRACE("(%p, %p)\n", iface, pStm);
616 if (!pStm)
617 return E_INVALIDARG;
619 /* release previously allocated stream */
620 if (This->stream) IStream_Release(This->stream);
621 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
622 if (FAILED(hr))
623 return hr;
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);
631 if (FAILED(hr))
633 ERR("Failed to copy stream\n");
634 return hr;
637 hr = GetHGlobalFromStream(This->stream, &hglobal);
638 if (FAILED(hr))
639 return hr;
641 len = GlobalSize(hglobal);
642 ptr = GlobalLock(hglobal);
643 if (len != 0)
645 xmlFreeDoc(This->xmldoc);
646 This->xmldoc = parse_xml(ptr, len);
648 GlobalUnlock(hglobal);
650 if (!This->xmldoc)
652 ERR("Failed to parse xml\n");
653 return E_FAIL;
656 return S_OK;
659 static HRESULT WINAPI xmldoc_IPersistStreamInit_Save(
660 IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty)
662 FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty);
663 return E_NOTIMPL;
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);
671 return E_NOTIMPL;
674 static HRESULT WINAPI xmldoc_IPersistStreamInit_InitNew(
675 IPersistStreamInit *iface)
677 xmldoc *This = impl_from_IPersistStreamInit(iface);
678 TRACE("(%p)\n", This);
679 return S_OK;
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)
697 xmldoc *doc;
699 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
701 doc = heap_alloc(sizeof (*doc));
702 if(!doc)
703 return E_OUTOFMEMORY;
705 doc->lpVtbl = &xmldoc_vtbl;
706 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
707 doc->ref = 1;
708 doc->error = S_OK;
709 doc->xmldoc = NULL;
710 doc->stream = NULL;
712 *ppObj = &doc->lpVtbl;
714 TRACE("returning iface %p\n", *ppObj);
715 return S_OK;
718 #else
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");
724 return E_NOTIMPL;
727 #endif