msxml3: Corrected Entity Reference Test.
[wine.git] / dlls / msxml3 / xmldoc.c
bloba4c0850b095da60dce8c88e9740d21d5eea06cbf
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 IXMLElement *root;
58 xmlDocPtr xmldoc;
60 /* IPersistStream */
61 IStream *stream;
62 } xmldoc;
64 static inline xmldoc *impl_from_IXMLDocument(IXMLDocument *iface)
66 return (xmldoc *)((char*)iface - FIELD_OFFSET(xmldoc, lpVtbl));
69 static inline xmldoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
71 return (xmldoc *)((char*)iface - FIELD_OFFSET(xmldoc, lpvtblIPersistStreamInit));
74 static HRESULT WINAPI xmldoc_QueryInterface(IXMLDocument *iface, REFIID riid, void** ppvObject)
76 xmldoc *This = impl_from_IXMLDocument(iface);
78 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
80 if (IsEqualGUID(riid, &IID_IUnknown) ||
81 IsEqualGUID(riid, &IID_IXMLDocument) ||
82 IsEqualGUID(riid, &IID_IXMLDOMDocument))
84 *ppvObject = iface;
86 else if (IsEqualGUID(&IID_IPersistStreamInit, riid) ||
87 IsEqualGUID(&IID_IPersistStream, riid))
89 *ppvObject = (IPersistStreamInit *)&(This->lpvtblIPersistStreamInit);
91 else
93 FIXME("interface %s not implemented\n", debugstr_guid(riid));
94 return E_NOINTERFACE;
97 IXMLDocument_AddRef(iface);
99 return S_OK;
102 static ULONG WINAPI xmldoc_AddRef(IXMLDocument *iface)
104 xmldoc *This = impl_from_IXMLDocument(iface);
105 TRACE("%p\n", This);
106 return InterlockedIncrement(&This->ref);
109 static ULONG WINAPI xmldoc_Release(IXMLDocument *iface)
111 xmldoc *This = impl_from_IXMLDocument(iface);
112 LONG ref;
114 TRACE("%p\n", This);
116 ref = InterlockedDecrement(&This->ref);
117 if (ref == 0)
119 xmlFreeDoc(This->xmldoc);
120 if (This->stream) IStream_Release(This->stream);
121 HeapFree(GetProcessHeap(), 0, This);
124 return ref;
127 static HRESULT WINAPI xmldoc_GetTypeInfoCount(IXMLDocument *iface, UINT* pctinfo)
129 FIXME("\n");
130 return E_NOTIMPL;
133 static HRESULT WINAPI xmldoc_GetTypeInfo(IXMLDocument *iface, UINT iTInfo,
134 LCID lcid, ITypeInfo** ppTInfo)
136 FIXME("\n");
137 return E_NOTIMPL;
140 static HRESULT WINAPI xmldoc_GetIDsOfNames(IXMLDocument *iface, REFIID riid,
141 LPOLESTR* rgszNames, UINT cNames,
142 LCID lcid, DISPID* rgDispId)
144 FIXME("\n");
145 return E_NOTIMPL;
148 static HRESULT WINAPI xmldoc_Invoke(IXMLDocument *iface, DISPID dispIdMember,
149 REFIID riid, LCID lcid, WORD wFlags,
150 DISPPARAMS* pDispParams, VARIANT* pVarResult,
151 EXCEPINFO* pExcepInfo, UINT* puArgErr)
153 FIXME("\n");
154 return E_NOTIMPL;
157 static HRESULT WINAPI xmldoc_get_root(IXMLDocument *iface, IXMLElement **p)
159 xmldoc *This = impl_from_IXMLDocument(iface);
161 TRACE("(%p, %p)\n", iface, p);
163 if (!p)
164 return E_INVALIDARG;
166 *p = This->root;
167 if (!*p)
168 return E_FAIL;
170 return S_OK;
173 static HRESULT WINAPI xmldoc_get_fileSize(IXMLDocument *iface, BSTR *p)
175 FIXME("(%p, %p): stub\n", iface, p);
176 return E_NOTIMPL;
179 static HRESULT WINAPI xmldoc_put_fileModifiedDate(IXMLDocument *iface, BSTR *p)
181 FIXME("(%p, %p): stub\n", iface, p);
182 return E_NOTIMPL;
185 static HRESULT WINAPI xmldoc_get_fileUpdatedDate(IXMLDocument *iface, BSTR *p)
187 FIXME("(%p, %p): stub\n", iface, p);
188 return E_NOTIMPL;
191 static HRESULT WINAPI xmldoc_get_URL(IXMLDocument *iface, BSTR *p)
193 FIXME("(%p, %p): stub\n", iface, p);
194 return E_NOTIMPL;
197 typedef struct {
198 const struct IBindStatusCallbackVtbl *lpVtbl;
199 } bsc;
201 static HRESULT WINAPI bsc_QueryInterface(
202 IBindStatusCallback *iface,
203 REFIID riid,
204 LPVOID *ppobj )
206 if (IsEqualGUID(riid, &IID_IUnknown) ||
207 IsEqualGUID(riid, &IID_IBindStatusCallback))
209 IBindStatusCallback_AddRef( iface );
210 *ppobj = iface;
211 return S_OK;
214 FIXME("interface %s not implemented\n", debugstr_guid(riid));
215 return E_NOINTERFACE;
218 static ULONG WINAPI bsc_AddRef(
219 IBindStatusCallback *iface )
221 return 2;
224 static ULONG WINAPI bsc_Release(
225 IBindStatusCallback *iface )
227 return 1;
230 static HRESULT WINAPI bsc_OnStartBinding(
231 IBindStatusCallback* iface,
232 DWORD dwReserved,
233 IBinding* pib)
235 return S_OK;
238 static HRESULT WINAPI bsc_GetPriority(
239 IBindStatusCallback* iface,
240 LONG* pnPriority)
242 return S_OK;
245 static HRESULT WINAPI bsc_OnLowResource(
246 IBindStatusCallback* iface,
247 DWORD reserved)
249 return S_OK;
252 static HRESULT WINAPI bsc_OnProgress(
253 IBindStatusCallback* iface,
254 ULONG ulProgress,
255 ULONG ulProgressMax,
256 ULONG ulStatusCode,
257 LPCWSTR szStatusText)
259 return S_OK;
262 static HRESULT WINAPI bsc_OnStopBinding(
263 IBindStatusCallback* iface,
264 HRESULT hresult,
265 LPCWSTR szError)
267 return S_OK;
270 static HRESULT WINAPI bsc_GetBindInfo(
271 IBindStatusCallback* iface,
272 DWORD* grfBINDF,
273 BINDINFO* pbindinfo)
275 *grfBINDF = BINDF_RESYNCHRONIZE;
277 return S_OK;
280 static HRESULT WINAPI bsc_OnDataAvailable(
281 IBindStatusCallback* iface,
282 DWORD grfBSCF,
283 DWORD dwSize,
284 FORMATETC* pformatetc,
285 STGMEDIUM* pstgmed)
287 return S_OK;
290 static HRESULT WINAPI bsc_OnObjectAvailable(
291 IBindStatusCallback* iface,
292 REFIID riid,
293 IUnknown* punk)
295 return S_OK;
298 static const struct IBindStatusCallbackVtbl bsc_vtbl =
300 bsc_QueryInterface,
301 bsc_AddRef,
302 bsc_Release,
303 bsc_OnStartBinding,
304 bsc_GetPriority,
305 bsc_OnLowResource,
306 bsc_OnProgress,
307 bsc_OnStopBinding,
308 bsc_GetBindInfo,
309 bsc_OnDataAvailable,
310 bsc_OnObjectAvailable
313 static bsc xmldoc_bsc = { &bsc_vtbl };
315 static HRESULT WINAPI xmldoc_put_URL(IXMLDocument *iface, BSTR p)
317 WCHAR url[INTERNET_MAX_URL_LENGTH];
318 IStream *stream;
319 IBindCtx *bctx;
320 IMoniker *moniker;
321 IPersistStreamInit *persist;
322 HRESULT hr;
324 TRACE("(%p, %s)\n", iface, debugstr_w(p));
326 if (!p)
327 return E_INVALIDARG;
329 if (!PathIsURLW(p))
331 WCHAR fullpath[MAX_PATH];
332 DWORD needed = sizeof(url) / sizeof(WCHAR);
334 if (!PathSearchAndQualifyW(p, fullpath, sizeof(fullpath) / sizeof(WCHAR)))
336 ERR("can't find path\n");
337 return E_FAIL;
340 if (FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0)))
342 ERR("can't create url from path\n");
343 return E_FAIL;
346 p = url;
349 hr = CreateURLMoniker(NULL, p, &moniker);
350 if (FAILED(hr))
351 return hr;
353 CreateAsyncBindCtx(0, (IBindStatusCallback *)&xmldoc_bsc, 0, &bctx);
355 hr = IMoniker_BindToStorage(moniker, bctx, NULL, &IID_IStream, (LPVOID *)&stream);
356 IBindCtx_Release(bctx);
357 IMoniker_Release(moniker);
358 if (FAILED(hr))
359 return hr;
361 hr = IXMLDocument_QueryInterface(iface, &IID_IPersistStreamInit, (LPVOID *)&persist);
362 if (FAILED(hr))
364 IStream_Release(stream);
365 return hr;
368 hr = IPersistStreamInit_Load(persist, stream);
369 IPersistStreamInit_Release(persist);
370 IStream_Release(stream);
372 return hr;
375 static HRESULT WINAPI xmldoc_get_mimeType(IXMLDocument *iface, BSTR *p)
377 FIXME("(%p, %p): stub\n", iface, p);
378 return E_NOTIMPL;
381 static HRESULT WINAPI xmldoc_get_readyState(IXMLDocument *iface, long *p)
383 FIXME("(%p, %p): stub\n", iface, p);
384 return E_NOTIMPL;
387 static HRESULT WINAPI xmldoc_get_charset(IXMLDocument *iface, BSTR *p)
389 FIXME("(%p, %p): stub\n", iface, p);
390 return E_NOTIMPL;
393 static HRESULT WINAPI xmldoc_put_charset(IXMLDocument *iface, BSTR p)
395 FIXME("(%p, %p): stub\n", iface, p);
396 return E_NOTIMPL;
399 static HRESULT WINAPI xmldoc_get_version(IXMLDocument *iface, BSTR *p)
401 FIXME("(%p, %p): stub\n", iface, p);
402 return E_NOTIMPL;
405 static HRESULT WINAPI xmldoc_get_doctype(IXMLDocument *iface, BSTR *p)
407 FIXME("(%p, %p): stub\n", iface, p);
408 return E_NOTIMPL;
411 static HRESULT WINAPI xmldoc_get_dtdURl(IXMLDocument *iface, BSTR *p)
413 FIXME("(%p, %p): stub\n", iface, p);
414 return E_NOTIMPL;
417 static xmlElementType type_msxml_to_libxml(long type)
419 switch (type)
421 case XMLELEMTYPE_ELEMENT:
422 return XML_ELEMENT_NODE;
423 case XMLELEMTYPE_TEXT:
424 return XML_TEXT_NODE;
425 case XMLELEMTYPE_COMMENT:
426 return XML_COMMENT_NODE;
427 case XMLELEMTYPE_DOCUMENT:
428 return XML_DOCUMENT_NODE;
429 case XMLELEMTYPE_DTD:
430 return XML_DTD_NODE;
431 case XMLELEMTYPE_PI:
432 return XML_PI_NODE;
433 default:
434 break;
437 return -1; /* FIXME: what is OTHER in msxml? */
440 static HRESULT WINAPI xmldoc_createElement(IXMLDocument *iface, VARIANT vType,
441 VARIANT var1, IXMLElement **ppElem)
443 xmlNodePtr node;
444 static const xmlChar empty[] = "\0";
446 TRACE("(%p, %p)\n", iface, ppElem);
448 if (!ppElem)
449 return E_INVALIDARG;
451 *ppElem = NULL;
453 if (V_VT(&vType) != VT_I4)
454 return E_INVALIDARG;
456 node = xmlNewNode(NULL, empty);
457 node->type = type_msxml_to_libxml(V_I4(&vType));
459 /* FIXME: create xmlNodePtr based on vType and var1 */
460 return XMLElement_create((IUnknown *)iface, node, (LPVOID *)ppElem);
463 static const struct IXMLDocumentVtbl xmldoc_vtbl =
465 xmldoc_QueryInterface,
466 xmldoc_AddRef,
467 xmldoc_Release,
468 xmldoc_GetTypeInfoCount,
469 xmldoc_GetTypeInfo,
470 xmldoc_GetIDsOfNames,
471 xmldoc_Invoke,
472 xmldoc_get_root,
473 xmldoc_get_fileSize,
474 xmldoc_put_fileModifiedDate,
475 xmldoc_get_fileUpdatedDate,
476 xmldoc_get_URL,
477 xmldoc_put_URL,
478 xmldoc_get_mimeType,
479 xmldoc_get_readyState,
480 xmldoc_get_charset,
481 xmldoc_put_charset,
482 xmldoc_get_version,
483 xmldoc_get_doctype,
484 xmldoc_get_dtdURl,
485 xmldoc_createElement
488 /************************************************************************
489 * xmldoc implementation of IPersistStreamInit.
491 static HRESULT WINAPI xmldoc_IPersistStreamInit_QueryInterface(
492 IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj)
494 xmldoc *this = impl_from_IPersistStreamInit(iface);
495 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
498 static ULONG WINAPI xmldoc_IPersistStreamInit_AddRef(
499 IPersistStreamInit *iface)
501 xmldoc *this = impl_from_IPersistStreamInit(iface);
502 return IXMLDocument_AddRef((IXMLDocument *)this);
505 static ULONG WINAPI xmldoc_IPersistStreamInit_Release(
506 IPersistStreamInit *iface)
508 xmldoc *this = impl_from_IPersistStreamInit(iface);
509 return IXMLDocument_Release((IXMLDocument *)this);
512 static HRESULT WINAPI xmldoc_IPersistStreamInit_GetClassID(
513 IPersistStreamInit *iface, CLSID *classid)
515 FIXME("(%p,%p): stub!\n", iface, classid);
516 return E_NOTIMPL;
519 static HRESULT WINAPI xmldoc_IPersistStreamInit_IsDirty(
520 IPersistStreamInit *iface)
522 FIXME("(%p): stub!\n", iface);
523 return E_NOTIMPL;
526 xmlDocPtr parse_xml(char *ptr, int len)
528 #ifdef HAVE_XMLREADMEMORY
529 return xmlReadMemory(ptr, len, NULL, NULL,
530 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS);
531 #else
532 return xmlParseMemory(ptr, len);
533 #endif
536 static HRESULT WINAPI xmldoc_IPersistStreamInit_Load(
537 IPersistStreamInit *iface, LPSTREAM pStm)
539 xmldoc *This = impl_from_IPersistStreamInit(iface);
540 xmlNodePtr xmlnode;
541 HRESULT hr;
542 HGLOBAL hglobal;
543 DWORD read, written, len;
544 BYTE buf[4096];
545 char *ptr;
547 TRACE("(%p, %p)\n", iface, pStm);
549 if (!pStm)
550 return E_INVALIDARG;
552 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
553 if (FAILED(hr))
554 return hr;
558 IStream_Read(pStm, buf, sizeof(buf), &read);
559 hr = IStream_Write(This->stream, buf, read, &written);
560 } while(SUCCEEDED(hr) && written != 0 && read != 0);
562 if (FAILED(hr))
564 ERR("Failed to copy stream\n");
565 return hr;
568 hr = GetHGlobalFromStream(This->stream, &hglobal);
569 if (FAILED(hr))
570 return hr;
572 len = GlobalSize(hglobal);
573 ptr = GlobalLock(hglobal);
574 if (len != 0)
575 This->xmldoc = parse_xml(ptr, len);
576 GlobalUnlock(hglobal);
578 if (!This->xmldoc)
580 ERR("Failed to parse xml\n");
581 return E_FAIL;
584 xmlnode = xmlDocGetRootElement(This->xmldoc);
585 return XMLElement_create((IUnknown *)This, xmlnode, (LPVOID *)&This->root);
588 static HRESULT WINAPI xmldoc_IPersistStreamInit_Save(
589 IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty)
591 FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty);
592 return E_NOTIMPL;
595 static HRESULT WINAPI xmldoc_IPersistStreamInit_GetSizeMax(
596 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
598 FIXME("(%p, %p): stub!\n", iface, pcbSize);
599 return E_NOTIMPL;
602 static HRESULT WINAPI xmldoc_IPersistStreamInit_InitNew(
603 IPersistStreamInit *iface)
605 FIXME("(%p): stub!\n", iface);
606 return E_NOTIMPL;
609 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
611 xmldoc_IPersistStreamInit_QueryInterface,
612 xmldoc_IPersistStreamInit_AddRef,
613 xmldoc_IPersistStreamInit_Release,
614 xmldoc_IPersistStreamInit_GetClassID,
615 xmldoc_IPersistStreamInit_IsDirty,
616 xmldoc_IPersistStreamInit_Load,
617 xmldoc_IPersistStreamInit_Save,
618 xmldoc_IPersistStreamInit_GetSizeMax,
619 xmldoc_IPersistStreamInit_InitNew
622 HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
624 xmldoc *doc;
626 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
628 doc = HeapAlloc(GetProcessHeap(), 0, sizeof (*doc));
629 if(!doc)
630 return E_OUTOFMEMORY;
632 doc->lpVtbl = &xmldoc_vtbl;
633 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
634 doc->ref = 1;
635 doc->error = S_OK;
636 doc->root = NULL;
637 doc->xmldoc = NULL;
638 doc->stream = NULL;
640 *ppObj = &doc->lpVtbl;
642 TRACE("returning iface %p\n", *ppObj);
643 return S_OK;
646 #else
648 HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
650 MESSAGE("This program tried to use an XMLDocument object, but\n"
651 "libxml2 support was not present at compile time.\n");
652 return E_NOTIMPL;
655 #endif