[MSXML3]
[reactos.git] / reactos / dll / win32 / msxml3 / domdoc.c
1 /*
2 * DOM Document implementation
3 *
4 * Copyright 2005 Mike McCormack
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define COBJMACROS
22 #define NONAMELESSUNION
23
24 #include "config.h"
25
26 #include <stdarg.h>
27 #include <assert.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winnls.h"
32 #include "ole2.h"
33 #include "msxml2.h"
34 #include "wininet.h"
35 #include "winreg.h"
36 #include "shlwapi.h"
37 #include "ocidl.h"
38 #include "objsafe.h"
39 #include "dispex.h"
40
41 #include "wine/debug.h"
42 #include "wine/list.h"
43
44 #include "msxml_private.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
47
48 #ifdef HAVE_LIBXML2
49
50 #include <libxml/xmlsave.h>
51
52 /* not defined in older versions */
53 #define XML_SAVE_FORMAT 1
54 #define XML_SAVE_NO_DECL 2
55 #define XML_SAVE_NO_EMPTY 4
56 #define XML_SAVE_NO_XHTML 8
57 #define XML_SAVE_XHTML 16
58 #define XML_SAVE_AS_XML 32
59 #define XML_SAVE_AS_HTML 64
60
61 static const WCHAR SZ_PROPERTY_SELECTION_LANGUAGE[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
62 static const WCHAR SZ_VALUE_XPATH[] = {'X','P','a','t','h',0};
63 static const WCHAR SZ_VALUE_XSLPATTERN[] = {'X','S','L','P','a','t','t','e','r','n',0};
64
65 typedef struct _domdoc
66 {
67 xmlnode node;
68 const struct IXMLDOMDocument2Vtbl *lpVtbl;
69 const struct IPersistStreamVtbl *lpvtblIPersistStream;
70 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
71 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
72 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
73 LONG ref;
74 VARIANT_BOOL async;
75 VARIANT_BOOL validating;
76 VARIANT_BOOL resolving;
77 VARIANT_BOOL preserving;
78 BOOL bUseXPath;
79 IXMLDOMSchemaCollection *schema;
80 bsc_t *bsc;
81 HRESULT error;
82
83 /* IPersistStream */
84 IStream *stream;
85
86 /* IObjectWithSite*/
87 IUnknown *site;
88
89 /* IObjectSafety */
90 DWORD safeopt;
91 } domdoc;
92
93 /*
94 In native windows, the whole lifetime management of XMLDOMNodes is
95 managed automatically using reference counts. Wine emulates that by
96 maintaining a reference count to the document that is increased for
97 each IXMLDOMNode pointer passed out for this document. If all these
98 pointers are gone, the document is unreachable and gets freed, that
99 is, all nodes in the tree of the document get freed.
100
101 You are able to create nodes that are associated to a document (in
102 fact, in msxml's XMLDOM model, all nodes are associated to a document),
103 but not in the tree of that document, for example using the createFoo
104 functions from IXMLDOMDocument. These nodes do not get cleaned up
105 by libxml, so we have to do it ourselves.
106
107 To catch these nodes, a list of "orphan nodes" is introduced.
108 It contains pointers to all roots of node trees that are
109 associated with the document without being part of the document
110 tree. All nodes with parent==NULL (except for the document root nodes)
111 should be in the orphan node list of their document. All orphan nodes
112 get freed together with the document itself.
113 */
114
115 typedef struct _xmldoc_priv {
116 LONG refs;
117 struct list orphans;
118 } xmldoc_priv;
119
120 typedef struct _orphan_entry {
121 struct list entry;
122 xmlNode * node;
123 } orphan_entry;
124
125 static inline xmldoc_priv * priv_from_xmlDocPtr(xmlDocPtr doc)
126 {
127 return doc->_private;
128 }
129
130 static xmldoc_priv * create_priv(void)
131 {
132 xmldoc_priv *priv;
133 priv = heap_alloc( sizeof (*priv) );
134
135 if(priv)
136 {
137 priv->refs = 0;
138 list_init( &priv->orphans );
139 }
140
141 return priv;
142 }
143
144 static xmlDocPtr doparse( char *ptr, int len )
145 {
146 #ifdef HAVE_XMLREADMEMORY
147 /*
148 * use xmlReadMemory if possible so we can suppress
149 * writing errors to stderr
150 */
151 return xmlReadMemory( ptr, len, NULL, NULL,
152 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
153 #else
154 return xmlParseMemory( ptr, len );
155 #endif
156 }
157
158 LONG xmldoc_add_ref(xmlDocPtr doc)
159 {
160 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
161 TRACE("%d\n", ref);
162 return ref;
163 }
164
165 LONG xmldoc_release(xmlDocPtr doc)
166 {
167 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
168 LONG ref = InterlockedDecrement(&priv->refs);
169 TRACE("%d\n", ref);
170 if(ref == 0)
171 {
172 orphan_entry *orphan, *orphan2;
173 TRACE("freeing docptr %p\n", doc);
174
175 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
176 {
177 xmlFreeNode( orphan->node );
178 heap_free( orphan );
179 }
180 heap_free(doc->_private);
181
182 xmlFreeDoc(doc);
183 }
184
185 return ref;
186 }
187
188 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
189 {
190 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
191 orphan_entry *entry;
192
193 entry = heap_alloc( sizeof (*entry) );
194 if(!entry)
195 return E_OUTOFMEMORY;
196
197 entry->node = node;
198 list_add_head( &priv->orphans, &entry->entry );
199 return S_OK;
200 }
201
202 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
203 {
204 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
205 orphan_entry *entry, *entry2;
206
207 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
208 {
209 if( entry->node == node )
210 {
211 list_remove( &entry->entry );
212 heap_free( entry );
213 return S_OK;
214 }
215 }
216
217 return S_FALSE;
218 }
219
220 static HRESULT attach_xmldoc( xmlnode *node, xmlDocPtr xml )
221 {
222 if(node->node)
223 xmldoc_release(node->node->doc);
224
225 node->node = (xmlNodePtr) xml;
226 if(node->node)
227 xmldoc_add_ref(node->node->doc);
228
229 return S_OK;
230 }
231
232 static inline domdoc *impl_from_IXMLDOMDocument2( IXMLDOMDocument2 *iface )
233 {
234 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
235 }
236
237 static inline xmlDocPtr get_doc( domdoc *This )
238 {
239 return (xmlDocPtr)This->node.node;
240 }
241
242 static inline domdoc *impl_from_IPersistStream(IPersistStream *iface)
243 {
244 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStream));
245 }
246
247 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
248 {
249 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
250 }
251
252 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
253 {
254 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
255 }
256
257 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
258 {
259 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
260 }
261
262 /************************************************************************
263 * xmldoc implementation of IPersistStream.
264 */
265 static HRESULT WINAPI xmldoc_IPersistStream_QueryInterface(
266 IPersistStream *iface, REFIID riid, LPVOID *ppvObj)
267 {
268 domdoc *this = impl_from_IPersistStream(iface);
269 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
270 }
271
272 static ULONG WINAPI xmldoc_IPersistStream_AddRef(
273 IPersistStream *iface)
274 {
275 domdoc *this = impl_from_IPersistStream(iface);
276 return IXMLDocument_AddRef((IXMLDocument *)this);
277 }
278
279 static ULONG WINAPI xmldoc_IPersistStream_Release(
280 IPersistStream *iface)
281 {
282 domdoc *this = impl_from_IPersistStream(iface);
283 return IXMLDocument_Release((IXMLDocument *)this);
284 }
285
286 static HRESULT WINAPI xmldoc_IPersistStream_GetClassID(
287 IPersistStream *iface, CLSID *classid)
288 {
289 TRACE("(%p,%p): stub!\n", iface, classid);
290
291 if(!classid)
292 return E_POINTER;
293
294 *classid = CLSID_DOMDocument2;
295
296 return S_OK;
297 }
298
299 static HRESULT WINAPI xmldoc_IPersistStream_IsDirty(
300 IPersistStream *iface)
301 {
302 domdoc *This = impl_from_IPersistStream(iface);
303
304 FIXME("(%p): stub!\n", This);
305
306 return S_FALSE;
307 }
308
309 static HRESULT WINAPI xmldoc_IPersistStream_Load(
310 IPersistStream *iface, LPSTREAM pStm)
311 {
312 domdoc *This = impl_from_IPersistStream(iface);
313 HRESULT hr;
314 HGLOBAL hglobal;
315 DWORD read, written, len;
316 BYTE buf[4096];
317 char *ptr;
318 xmlDocPtr xmldoc = NULL;
319
320 TRACE("(%p)->(%p)\n", This, pStm);
321
322 if (!pStm)
323 return E_INVALIDARG;
324
325 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
326 if (FAILED(hr))
327 return hr;
328
329 do
330 {
331 IStream_Read(pStm, buf, sizeof(buf), &read);
332 hr = IStream_Write(This->stream, buf, read, &written);
333 } while(SUCCEEDED(hr) && written != 0 && read != 0);
334
335 if (FAILED(hr))
336 {
337 ERR("Failed to copy stream\n");
338 return hr;
339 }
340
341 hr = GetHGlobalFromStream(This->stream, &hglobal);
342 if (FAILED(hr))
343 return hr;
344
345 len = GlobalSize(hglobal);
346 ptr = GlobalLock(hglobal);
347 if (len != 0)
348 xmldoc = parse_xml(ptr, len);
349 GlobalUnlock(hglobal);
350
351 if (!xmldoc)
352 {
353 ERR("Failed to parse xml\n");
354 return E_FAIL;
355 }
356
357 xmldoc->_private = create_priv();
358
359 return attach_xmldoc( &This->node, xmldoc );
360 }
361
362 static HRESULT WINAPI xmldoc_IPersistStream_Save(
363 IPersistStream *iface, LPSTREAM pStm, BOOL fClearDirty)
364 {
365 domdoc *This = impl_from_IPersistStream(iface);
366 HRESULT hr;
367 BSTR xmlString;
368
369 TRACE("(%p)->(%p %d)\n", This, pStm, fClearDirty);
370
371 hr = IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), &xmlString );
372 if(hr == S_OK)
373 {
374 DWORD count;
375 DWORD len = strlenW(xmlString) * sizeof(WCHAR);
376
377 hr = IStream_Write( pStm, xmlString, len, &count );
378
379 SysFreeString(xmlString);
380 }
381
382 TRACE("ret 0x%08x\n", hr);
383
384 return hr;
385 }
386
387 static HRESULT WINAPI xmldoc_IPersistStream_GetSizeMax(
388 IPersistStream *iface, ULARGE_INTEGER *pcbSize)
389 {
390 domdoc *This = impl_from_IPersistStream(iface);
391 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
392 return E_NOTIMPL;
393 }
394
395 static const IPersistStreamVtbl xmldoc_IPersistStream_VTable =
396 {
397 xmldoc_IPersistStream_QueryInterface,
398 xmldoc_IPersistStream_AddRef,
399 xmldoc_IPersistStream_Release,
400 xmldoc_IPersistStream_GetClassID,
401 xmldoc_IPersistStream_IsDirty,
402 xmldoc_IPersistStream_Load,
403 xmldoc_IPersistStream_Save,
404 xmldoc_IPersistStream_GetSizeMax,
405 };
406
407 /* ISupportErrorInfo interface */
408 static HRESULT WINAPI support_error_QueryInterface(
409 ISupportErrorInfo *iface,
410 REFIID riid, void** ppvObj )
411 {
412 domdoc *This = impl_from_ISupportErrorInfo(iface);
413 return IXMLDocument_QueryInterface((IXMLDocument *)This, riid, ppvObj);
414 }
415
416 static ULONG WINAPI support_error_AddRef(
417 ISupportErrorInfo *iface )
418 {
419 domdoc *This = impl_from_ISupportErrorInfo(iface);
420 return IXMLDocument_AddRef((IXMLDocument *)This);
421 }
422
423 static ULONG WINAPI support_error_Release(
424 ISupportErrorInfo *iface )
425 {
426 domdoc *This = impl_from_ISupportErrorInfo(iface);
427 return IXMLDocument_Release((IXMLDocument *)This);
428 }
429
430 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
431 ISupportErrorInfo *iface,
432 REFIID riid )
433 {
434 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
435 return S_FALSE;
436 }
437
438 static const struct ISupportErrorInfoVtbl support_error_vtbl =
439 {
440 support_error_QueryInterface,
441 support_error_AddRef,
442 support_error_Release,
443 support_error_InterfaceSupportsErrorInfo
444 };
445
446 /* IXMLDOMDocument2 interface */
447 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject )
448 {
449 domdoc *This = impl_from_IXMLDOMDocument2( iface );
450
451 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
452
453 *ppvObject = NULL;
454
455 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
456 IsEqualGUID( riid, &IID_IDispatch ) ||
457 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
458 IsEqualGUID( riid, &IID_IXMLDOMDocument2 ) )
459 {
460 *ppvObject = iface;
461 }
462 else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
463 {
464 *ppvObject = IXMLDOMNode_from_impl(&This->node);
465 }
466 else if (IsEqualGUID(&IID_IPersistStream, riid))
467 {
468 *ppvObject = &(This->lpvtblIPersistStream);
469 }
470 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
471 {
472 *ppvObject = &(This->lpvtblIObjectWithSite);
473 }
474 else if (IsEqualGUID(&IID_IObjectSafety, riid))
475 {
476 *ppvObject = &(This->lpvtblIObjectSafety);
477 }
478 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
479 {
480 *ppvObject = &This->lpvtblISupportErrorInfo;
481 }
482 else if(dispex_query_interface(&This->node.dispex, riid, ppvObject))
483 {
484 return *ppvObject ? S_OK : E_NOINTERFACE;
485 }
486 else if(IsEqualGUID(&IID_IRunnableObject, riid))
487 {
488 TRACE("IID_IRunnableObject not supported returning NULL\n");
489 return E_NOINTERFACE;
490 }
491 else
492 {
493 FIXME("interface %s not implemented\n", debugstr_guid(riid));
494 return E_NOINTERFACE;
495 }
496
497 IUnknown_AddRef((IUnknown*)*ppvObject);
498
499 return S_OK;
500 }
501
502
503 static ULONG WINAPI domdoc_AddRef(
504 IXMLDOMDocument2 *iface )
505 {
506 domdoc *This = impl_from_IXMLDOMDocument2( iface );
507 TRACE("%p\n", This );
508 return InterlockedIncrement( &This->ref );
509 }
510
511
512 static ULONG WINAPI domdoc_Release(
513 IXMLDOMDocument2 *iface )
514 {
515 domdoc *This = impl_from_IXMLDOMDocument2( iface );
516 LONG ref;
517
518 TRACE("%p\n", This );
519
520 ref = InterlockedDecrement( &This->ref );
521 if ( ref == 0 )
522 {
523 if(This->bsc)
524 detach_bsc(This->bsc);
525
526 if (This->site)
527 IUnknown_Release( This->site );
528 destroy_xmlnode(&This->node);
529 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
530 if (This->stream) IStream_Release(This->stream);
531 HeapFree( GetProcessHeap(), 0, This );
532 }
533
534 return ref;
535 }
536
537 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument2 *iface, UINT* pctinfo )
538 {
539 domdoc *This = impl_from_IXMLDOMDocument2( iface );
540
541 TRACE("(%p)->(%p)\n", This, pctinfo);
542
543 *pctinfo = 1;
544
545 return S_OK;
546 }
547
548 static HRESULT WINAPI domdoc_GetTypeInfo(
549 IXMLDOMDocument2 *iface,
550 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
551 {
552 domdoc *This = impl_from_IXMLDOMDocument2( iface );
553 HRESULT hr;
554
555 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
556
557 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
558
559 return hr;
560 }
561
562 static HRESULT WINAPI domdoc_GetIDsOfNames(
563 IXMLDOMDocument2 *iface,
564 REFIID riid,
565 LPOLESTR* rgszNames,
566 UINT cNames,
567 LCID lcid,
568 DISPID* rgDispId)
569 {
570 domdoc *This = impl_from_IXMLDOMDocument2( iface );
571 ITypeInfo *typeinfo;
572 HRESULT hr;
573
574 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
575 lcid, rgDispId);
576
577 if(!rgszNames || cNames == 0 || !rgDispId)
578 return E_INVALIDARG;
579
580 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
581 if(SUCCEEDED(hr))
582 {
583 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
584 ITypeInfo_Release(typeinfo);
585 }
586
587 return hr;
588 }
589
590
591 static HRESULT WINAPI domdoc_Invoke(
592 IXMLDOMDocument2 *iface,
593 DISPID dispIdMember,
594 REFIID riid,
595 LCID lcid,
596 WORD wFlags,
597 DISPPARAMS* pDispParams,
598 VARIANT* pVarResult,
599 EXCEPINFO* pExcepInfo,
600 UINT* puArgErr)
601 {
602 domdoc *This = impl_from_IXMLDOMDocument2( iface );
603 ITypeInfo *typeinfo;
604 HRESULT hr;
605
606 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
607 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
608
609 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
610 if(SUCCEEDED(hr))
611 {
612 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
613 pVarResult, pExcepInfo, puArgErr);
614 ITypeInfo_Release(typeinfo);
615 }
616
617 return hr;
618 }
619
620
621 static HRESULT WINAPI domdoc_get_nodeName(
622 IXMLDOMDocument2 *iface,
623 BSTR* name )
624 {
625 domdoc *This = impl_from_IXMLDOMDocument2( iface );
626 return IXMLDOMNode_get_nodeName( IXMLDOMNode_from_impl(&This->node), name );
627 }
628
629
630 static HRESULT WINAPI domdoc_get_nodeValue(
631 IXMLDOMDocument2 *iface,
632 VARIANT* value )
633 {
634 domdoc *This = impl_from_IXMLDOMDocument2( iface );
635 return IXMLDOMNode_get_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
636 }
637
638
639 static HRESULT WINAPI domdoc_put_nodeValue(
640 IXMLDOMDocument2 *iface,
641 VARIANT value)
642 {
643 domdoc *This = impl_from_IXMLDOMDocument2( iface );
644 return IXMLDOMNode_put_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
645 }
646
647
648 static HRESULT WINAPI domdoc_get_nodeType(
649 IXMLDOMDocument2 *iface,
650 DOMNodeType* type )
651 {
652 domdoc *This = impl_from_IXMLDOMDocument2( iface );
653 return IXMLDOMNode_get_nodeType( IXMLDOMNode_from_impl(&This->node), type );
654 }
655
656
657 static HRESULT WINAPI domdoc_get_parentNode(
658 IXMLDOMDocument2 *iface,
659 IXMLDOMNode** parent )
660 {
661 domdoc *This = impl_from_IXMLDOMDocument2( iface );
662 return IXMLDOMNode_get_parentNode( IXMLDOMNode_from_impl(&This->node), parent );
663 }
664
665
666 static HRESULT WINAPI domdoc_get_childNodes(
667 IXMLDOMDocument2 *iface,
668 IXMLDOMNodeList** childList )
669 {
670 domdoc *This = impl_from_IXMLDOMDocument2( iface );
671 return IXMLDOMNode_get_childNodes( IXMLDOMNode_from_impl(&This->node), childList );
672 }
673
674
675 static HRESULT WINAPI domdoc_get_firstChild(
676 IXMLDOMDocument2 *iface,
677 IXMLDOMNode** firstChild )
678 {
679 domdoc *This = impl_from_IXMLDOMDocument2( iface );
680 return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), firstChild );
681 }
682
683
684 static HRESULT WINAPI domdoc_get_lastChild(
685 IXMLDOMDocument2 *iface,
686 IXMLDOMNode** lastChild )
687 {
688 domdoc *This = impl_from_IXMLDOMDocument2( iface );
689 return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), lastChild );
690 }
691
692
693 static HRESULT WINAPI domdoc_get_previousSibling(
694 IXMLDOMDocument2 *iface,
695 IXMLDOMNode** previousSibling )
696 {
697 domdoc *This = impl_from_IXMLDOMDocument2( iface );
698 return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), previousSibling );
699 }
700
701
702 static HRESULT WINAPI domdoc_get_nextSibling(
703 IXMLDOMDocument2 *iface,
704 IXMLDOMNode** nextSibling )
705 {
706 domdoc *This = impl_from_IXMLDOMDocument2( iface );
707 return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), nextSibling );
708 }
709
710
711 static HRESULT WINAPI domdoc_get_attributes(
712 IXMLDOMDocument2 *iface,
713 IXMLDOMNamedNodeMap** attributeMap )
714 {
715 domdoc *This = impl_from_IXMLDOMDocument2( iface );
716 return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
717 }
718
719
720 static HRESULT WINAPI domdoc_insertBefore(
721 IXMLDOMDocument2 *iface,
722 IXMLDOMNode* newChild,
723 VARIANT refChild,
724 IXMLDOMNode** outNewChild )
725 {
726 domdoc *This = impl_from_IXMLDOMDocument2( iface );
727 return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newChild, refChild, outNewChild );
728 }
729
730
731 static HRESULT WINAPI domdoc_replaceChild(
732 IXMLDOMDocument2 *iface,
733 IXMLDOMNode* newChild,
734 IXMLDOMNode* oldChild,
735 IXMLDOMNode** outOldChild)
736 {
737 domdoc *This = impl_from_IXMLDOMDocument2( iface );
738 return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newChild, oldChild, outOldChild );
739 }
740
741
742 static HRESULT WINAPI domdoc_removeChild(
743 IXMLDOMDocument2 *iface,
744 IXMLDOMNode* childNode,
745 IXMLDOMNode** oldChild)
746 {
747 domdoc *This = impl_from_IXMLDOMDocument2( iface );
748 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
749 }
750
751
752 static HRESULT WINAPI domdoc_appendChild(
753 IXMLDOMDocument2 *iface,
754 IXMLDOMNode* newChild,
755 IXMLDOMNode** outNewChild)
756 {
757 domdoc *This = impl_from_IXMLDOMDocument2( iface );
758 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
759 }
760
761
762 static HRESULT WINAPI domdoc_hasChildNodes(
763 IXMLDOMDocument2 *iface,
764 VARIANT_BOOL* hasChild)
765 {
766 domdoc *This = impl_from_IXMLDOMDocument2( iface );
767 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
768 }
769
770
771 static HRESULT WINAPI domdoc_get_ownerDocument(
772 IXMLDOMDocument2 *iface,
773 IXMLDOMDocument** DOMDocument)
774 {
775 domdoc *This = impl_from_IXMLDOMDocument2( iface );
776 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
777 }
778
779
780 static HRESULT WINAPI domdoc_cloneNode(
781 IXMLDOMDocument2 *iface,
782 VARIANT_BOOL deep,
783 IXMLDOMNode** cloneRoot)
784 {
785 domdoc *This = impl_from_IXMLDOMDocument2( iface );
786 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
787 }
788
789
790 static HRESULT WINAPI domdoc_get_nodeTypeString(
791 IXMLDOMDocument2 *iface,
792 BSTR* nodeType )
793 {
794 domdoc *This = impl_from_IXMLDOMDocument2( iface );
795 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
796 }
797
798
799 static HRESULT WINAPI domdoc_get_text(
800 IXMLDOMDocument2 *iface,
801 BSTR* text )
802 {
803 domdoc *This = impl_from_IXMLDOMDocument2( iface );
804 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
805 }
806
807
808 static HRESULT WINAPI domdoc_put_text(
809 IXMLDOMDocument2 *iface,
810 BSTR text )
811 {
812 domdoc *This = impl_from_IXMLDOMDocument2( iface );
813 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
814 }
815
816
817 static HRESULT WINAPI domdoc_get_specified(
818 IXMLDOMDocument2 *iface,
819 VARIANT_BOOL* isSpecified )
820 {
821 domdoc *This = impl_from_IXMLDOMDocument2( iface );
822 return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
823 }
824
825
826 static HRESULT WINAPI domdoc_get_definition(
827 IXMLDOMDocument2 *iface,
828 IXMLDOMNode** definitionNode )
829 {
830 domdoc *This = impl_from_IXMLDOMDocument2( iface );
831 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
832 }
833
834
835 static HRESULT WINAPI domdoc_get_nodeTypedValue(
836 IXMLDOMDocument2 *iface,
837 VARIANT* typedValue )
838 {
839 domdoc *This = impl_from_IXMLDOMDocument2( iface );
840 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
841 }
842
843 static HRESULT WINAPI domdoc_put_nodeTypedValue(
844 IXMLDOMDocument2 *iface,
845 VARIANT typedValue )
846 {
847 domdoc *This = impl_from_IXMLDOMDocument2( iface );
848 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
849 }
850
851
852 static HRESULT WINAPI domdoc_get_dataType(
853 IXMLDOMDocument2 *iface,
854 VARIANT* dataTypeName )
855 {
856 domdoc *This = impl_from_IXMLDOMDocument2( iface );
857 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
858 }
859
860
861 static HRESULT WINAPI domdoc_put_dataType(
862 IXMLDOMDocument2 *iface,
863 BSTR dataTypeName )
864 {
865 domdoc *This = impl_from_IXMLDOMDocument2( iface );
866 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
867 }
868
869
870 static HRESULT WINAPI domdoc_get_xml(
871 IXMLDOMDocument2 *iface,
872 BSTR* xmlString )
873 {
874 domdoc *This = impl_from_IXMLDOMDocument2( iface );
875 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
876 }
877
878
879 static HRESULT WINAPI domdoc_transformNode(
880 IXMLDOMDocument2 *iface,
881 IXMLDOMNode* styleSheet,
882 BSTR* xmlString )
883 {
884 domdoc *This = impl_from_IXMLDOMDocument2( iface );
885 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
886 }
887
888
889 static HRESULT WINAPI domdoc_selectNodes(
890 IXMLDOMDocument2 *iface,
891 BSTR queryString,
892 IXMLDOMNodeList** resultList )
893 {
894 domdoc *This = impl_from_IXMLDOMDocument2( iface );
895 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
896 }
897
898
899 static HRESULT WINAPI domdoc_selectSingleNode(
900 IXMLDOMDocument2 *iface,
901 BSTR queryString,
902 IXMLDOMNode** resultNode )
903 {
904 domdoc *This = impl_from_IXMLDOMDocument2( iface );
905 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
906 }
907
908
909 static HRESULT WINAPI domdoc_get_parsed(
910 IXMLDOMDocument2 *iface,
911 VARIANT_BOOL* isParsed )
912 {
913 domdoc *This = impl_from_IXMLDOMDocument2( iface );
914 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
915 }
916
917
918 static HRESULT WINAPI domdoc_get_namespaceURI(
919 IXMLDOMDocument2 *iface,
920 BSTR* namespaceURI )
921 {
922 domdoc *This = impl_from_IXMLDOMDocument2( iface );
923 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
924 }
925
926
927 static HRESULT WINAPI domdoc_get_prefix(
928 IXMLDOMDocument2 *iface,
929 BSTR* prefixString )
930 {
931 domdoc *This = impl_from_IXMLDOMDocument2( iface );
932 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
933 }
934
935
936 static HRESULT WINAPI domdoc_get_baseName(
937 IXMLDOMDocument2 *iface,
938 BSTR* nameString )
939 {
940 domdoc *This = impl_from_IXMLDOMDocument2( iface );
941 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
942 }
943
944
945 static HRESULT WINAPI domdoc_transformNodeToObject(
946 IXMLDOMDocument2 *iface,
947 IXMLDOMNode* stylesheet,
948 VARIANT outputObject)
949 {
950 domdoc *This = impl_from_IXMLDOMDocument2( iface );
951 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
952 }
953
954
955 static HRESULT WINAPI domdoc_get_doctype(
956 IXMLDOMDocument2 *iface,
957 IXMLDOMDocumentType** documentType )
958 {
959 domdoc *This = impl_from_IXMLDOMDocument2(iface);
960 FIXME("(%p)\n", This);
961 return E_NOTIMPL;
962 }
963
964
965 static HRESULT WINAPI domdoc_get_implementation(
966 IXMLDOMDocument2 *iface,
967 IXMLDOMImplementation** impl )
968 {
969 domdoc *This = impl_from_IXMLDOMDocument2(iface);
970
971 TRACE("(%p)->(%p)\n", This, impl);
972
973 if(!impl)
974 return E_INVALIDARG;
975
976 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
977
978 return S_OK;
979 }
980
981 static HRESULT WINAPI domdoc_get_documentElement(
982 IXMLDOMDocument2 *iface,
983 IXMLDOMElement** DOMElement )
984 {
985 domdoc *This = impl_from_IXMLDOMDocument2( iface );
986 xmlDocPtr xmldoc = NULL;
987 xmlNodePtr root = NULL;
988 IXMLDOMNode *element_node;
989 HRESULT hr;
990
991 TRACE("(%p)->(%p)\n", This, DOMElement);
992
993 if(!DOMElement)
994 return E_INVALIDARG;
995
996 *DOMElement = NULL;
997
998 xmldoc = get_doc( This );
999
1000 root = xmlDocGetRootElement( xmldoc );
1001 if ( !root )
1002 return S_FALSE;
1003
1004 element_node = create_node( root );
1005 if(!element_node) return S_FALSE;
1006
1007 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
1008 IXMLDOMNode_Release(element_node);
1009
1010 return hr;
1011 }
1012
1013
1014 static HRESULT WINAPI domdoc_put_documentElement(
1015 IXMLDOMDocument2 *iface,
1016 IXMLDOMElement* DOMElement )
1017 {
1018 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1019 IXMLDOMNode *elementNode;
1020 xmlNodePtr oldRoot;
1021 xmlnode *xmlNode;
1022 HRESULT hr;
1023
1024 TRACE("(%p)->(%p)\n", This, DOMElement);
1025
1026 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1027 if(FAILED(hr))
1028 return hr;
1029
1030 xmlNode = impl_from_IXMLDOMNode( elementNode );
1031
1032 if(!xmlNode->node->parent)
1033 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1034 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1035
1036 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1037 IXMLDOMNode_Release( elementNode );
1038
1039 if(oldRoot)
1040 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1041
1042 return S_OK;
1043 }
1044
1045
1046 static HRESULT WINAPI domdoc_createElement(
1047 IXMLDOMDocument2 *iface,
1048 BSTR tagname,
1049 IXMLDOMElement** element )
1050 {
1051 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1052 IXMLDOMNode *node;
1053 VARIANT type;
1054 HRESULT hr;
1055
1056 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1057
1058 if (!element || !tagname) return E_INVALIDARG;
1059
1060 V_VT(&type) = VT_I1;
1061 V_I1(&type) = NODE_ELEMENT;
1062
1063 hr = IXMLDOMDocument_createNode(iface, type, tagname, NULL, &node);
1064 if (hr == S_OK)
1065 {
1066 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1067 IXMLDOMNode_Release(node);
1068 }
1069
1070 return hr;
1071 }
1072
1073
1074 static HRESULT WINAPI domdoc_createDocumentFragment(
1075 IXMLDOMDocument2 *iface,
1076 IXMLDOMDocumentFragment** frag )
1077 {
1078 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1079 IXMLDOMNode *node;
1080 VARIANT type;
1081 HRESULT hr;
1082
1083 TRACE("(%p)->(%p)\n", This, frag);
1084
1085 if (!frag) return E_INVALIDARG;
1086
1087 *frag = NULL;
1088
1089 V_VT(&type) = VT_I1;
1090 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1091
1092 hr = IXMLDOMDocument_createNode(iface, type, NULL, NULL, &node);
1093 if (hr == S_OK)
1094 {
1095 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1096 IXMLDOMNode_Release(node);
1097 }
1098
1099 return hr;
1100 }
1101
1102
1103 static HRESULT WINAPI domdoc_createTextNode(
1104 IXMLDOMDocument2 *iface,
1105 BSTR data,
1106 IXMLDOMText** text )
1107 {
1108 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1109 IXMLDOMNode *node;
1110 VARIANT type;
1111 HRESULT hr;
1112
1113 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1114
1115 if (!text) return E_INVALIDARG;
1116
1117 *text = NULL;
1118
1119 V_VT(&type) = VT_I1;
1120 V_I1(&type) = NODE_TEXT;
1121
1122 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1123 if (hr == S_OK)
1124 {
1125 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1126 IXMLDOMNode_Release(node);
1127 hr = IXMLDOMText_put_data(*text, data);
1128 }
1129
1130 return hr;
1131 }
1132
1133
1134 static HRESULT WINAPI domdoc_createComment(
1135 IXMLDOMDocument2 *iface,
1136 BSTR data,
1137 IXMLDOMComment** comment )
1138 {
1139 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1140 VARIANT type;
1141 HRESULT hr;
1142 IXMLDOMNode *node;
1143
1144 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1145
1146 if (!comment) return E_INVALIDARG;
1147
1148 *comment = NULL;
1149
1150 V_VT(&type) = VT_I1;
1151 V_I1(&type) = NODE_COMMENT;
1152
1153 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1154 if (hr == S_OK)
1155 {
1156 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1157 IXMLDOMNode_Release(node);
1158 hr = IXMLDOMComment_put_data(*comment, data);
1159 }
1160
1161 return hr;
1162 }
1163
1164
1165 static HRESULT WINAPI domdoc_createCDATASection(
1166 IXMLDOMDocument2 *iface,
1167 BSTR data,
1168 IXMLDOMCDATASection** cdata )
1169 {
1170 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1171 IXMLDOMNode *node;
1172 VARIANT type;
1173 HRESULT hr;
1174
1175 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1176
1177 if (!cdata) return E_INVALIDARG;
1178
1179 *cdata = NULL;
1180
1181 V_VT(&type) = VT_I1;
1182 V_I1(&type) = NODE_CDATA_SECTION;
1183
1184 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1185 if (hr == S_OK)
1186 {
1187 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1188 IXMLDOMNode_Release(node);
1189 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1190 }
1191
1192 return hr;
1193 }
1194
1195
1196 static HRESULT WINAPI domdoc_createProcessingInstruction(
1197 IXMLDOMDocument2 *iface,
1198 BSTR target,
1199 BSTR data,
1200 IXMLDOMProcessingInstruction** pi )
1201 {
1202 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1203 IXMLDOMNode *node;
1204 VARIANT type;
1205 HRESULT hr;
1206
1207 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1208
1209 if (!pi) return E_INVALIDARG;
1210
1211 *pi = NULL;
1212
1213 V_VT(&type) = VT_I1;
1214 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1215
1216 hr = IXMLDOMDocument2_createNode(iface, type, target, NULL, &node);
1217 if (hr == S_OK)
1218 {
1219 VARIANT v_data;
1220
1221 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1222 V_VT(&v_data) = VT_BSTR;
1223 V_BSTR(&v_data) = data;
1224
1225 hr = IXMLDOMNode_put_nodeValue( node, v_data );
1226
1227 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1228 IXMLDOMNode_Release(node);
1229 }
1230
1231 return hr;
1232 }
1233
1234
1235 static HRESULT WINAPI domdoc_createAttribute(
1236 IXMLDOMDocument2 *iface,
1237 BSTR name,
1238 IXMLDOMAttribute** attribute )
1239 {
1240 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1241 IXMLDOMNode *node;
1242 VARIANT type;
1243 HRESULT hr;
1244
1245 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1246
1247 if (!attribute || !name) return E_INVALIDARG;
1248
1249 V_VT(&type) = VT_I1;
1250 V_I1(&type) = NODE_ATTRIBUTE;
1251
1252 hr = IXMLDOMDocument_createNode(iface, type, name, NULL, &node);
1253 if (hr == S_OK)
1254 {
1255 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1256 IXMLDOMNode_Release(node);
1257 }
1258
1259 return hr;
1260 }
1261
1262
1263 static HRESULT WINAPI domdoc_createEntityReference(
1264 IXMLDOMDocument2 *iface,
1265 BSTR name,
1266 IXMLDOMEntityReference** entityref )
1267 {
1268 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1269 IXMLDOMNode *node;
1270 VARIANT type;
1271 HRESULT hr;
1272
1273 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1274
1275 if (!entityref) return E_INVALIDARG;
1276
1277 *entityref = NULL;
1278
1279 V_VT(&type) = VT_I1;
1280 V_I1(&type) = NODE_ENTITY_REFERENCE;
1281
1282 hr = IXMLDOMDocument2_createNode(iface, type, name, NULL, &node);
1283 if (hr == S_OK)
1284 {
1285 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1286 IXMLDOMNode_Release(node);
1287 }
1288
1289 return hr;
1290 }
1291
1292
1293 static HRESULT WINAPI domdoc_getElementsByTagName(
1294 IXMLDOMDocument2 *iface,
1295 BSTR tagName,
1296 IXMLDOMNodeList** resultList )
1297 {
1298 static const WCHAR xpathformat[] =
1299 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'','%','s','\'',']',0 };
1300 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1301 LPWSTR szPattern;
1302 HRESULT hr;
1303 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1304
1305 if (tagName[0] == '*' && tagName[1] == 0)
1306 {
1307 szPattern = heap_alloc(sizeof(WCHAR)*4);
1308 szPattern[0] = szPattern[1] = '/';
1309 szPattern[2] = '*';
1310 szPattern[3] = 0;
1311 }
1312 else
1313 {
1314 szPattern = heap_alloc(sizeof(WCHAR)*(20+lstrlenW(tagName)+1));
1315 wsprintfW(szPattern, xpathformat, tagName);
1316 }
1317
1318 hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1319 heap_free(szPattern);
1320
1321 return hr;
1322 }
1323
1324 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1325 {
1326 VARIANT tmp;
1327 HRESULT hr;
1328
1329 VariantInit(&tmp);
1330 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1331 if(FAILED(hr))
1332 return E_INVALIDARG;
1333
1334 *type = V_I4(&tmp);
1335
1336 return S_OK;
1337 }
1338
1339 static HRESULT WINAPI domdoc_createNode(
1340 IXMLDOMDocument2 *iface,
1341 VARIANT Type,
1342 BSTR name,
1343 BSTR namespaceURI,
1344 IXMLDOMNode** node )
1345 {
1346 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1347 DOMNodeType node_type;
1348 xmlNodePtr xmlnode;
1349 xmlChar *xml_name;
1350 HRESULT hr;
1351
1352 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1353
1354 if(!node) return E_INVALIDARG;
1355
1356 if(namespaceURI && namespaceURI[0])
1357 FIXME("nodes with namespaces currently not supported.\n");
1358
1359 hr = get_node_type(Type, &node_type);
1360 if(FAILED(hr)) return hr;
1361
1362 TRACE("node_type %d\n", node_type);
1363
1364 /* exit earlier for types that need name */
1365 switch(node_type)
1366 {
1367 case NODE_ELEMENT:
1368 case NODE_ATTRIBUTE:
1369 case NODE_ENTITY_REFERENCE:
1370 case NODE_PROCESSING_INSTRUCTION:
1371 if (!name || SysStringLen(name) == 0) return E_FAIL;
1372 default:
1373 break;
1374 }
1375
1376 xml_name = xmlChar_from_wchar(name);
1377
1378 switch(node_type)
1379 {
1380 case NODE_ELEMENT:
1381 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1382 break;
1383 case NODE_ATTRIBUTE:
1384 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1385 break;
1386 case NODE_TEXT:
1387 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1388 break;
1389 case NODE_CDATA_SECTION:
1390 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1391 break;
1392 case NODE_ENTITY_REFERENCE:
1393 xmlnode = xmlNewReference(get_doc(This), xml_name);
1394 break;
1395 case NODE_PROCESSING_INSTRUCTION:
1396 #ifdef HAVE_XMLNEWDOCPI
1397 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1398 #else
1399 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1400 xmlnode = NULL;
1401 #endif
1402 break;
1403 case NODE_COMMENT:
1404 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1405 break;
1406 case NODE_DOCUMENT_FRAGMENT:
1407 xmlnode = xmlNewDocFragment(get_doc(This));
1408 break;
1409 /* unsupported types */
1410 case NODE_DOCUMENT:
1411 case NODE_DOCUMENT_TYPE:
1412 case NODE_ENTITY:
1413 case NODE_NOTATION:
1414 heap_free(xml_name);
1415 return E_INVALIDARG;
1416 default:
1417 FIXME("unhandled node type %d\n", node_type);
1418 xmlnode = NULL;
1419 break;
1420 }
1421
1422 *node = create_node(xmlnode);
1423 heap_free(xml_name);
1424
1425 if(*node)
1426 {
1427 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1428 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1429 return S_OK;
1430 }
1431
1432 return E_FAIL;
1433 }
1434
1435 static HRESULT WINAPI domdoc_nodeFromID(
1436 IXMLDOMDocument2 *iface,
1437 BSTR idString,
1438 IXMLDOMNode** node )
1439 {
1440 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1441 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1442 return E_NOTIMPL;
1443 }
1444
1445 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1446 {
1447 domdoc *This = obj;
1448 xmlDocPtr xmldoc;
1449
1450 xmldoc = doparse( ptr, len );
1451 if(xmldoc) {
1452 xmldoc->_private = create_priv();
1453 return attach_xmldoc(&This->node, xmldoc);
1454 }
1455
1456 return S_OK;
1457 }
1458
1459 static HRESULT doread( domdoc *This, LPWSTR filename )
1460 {
1461 bsc_t *bsc;
1462 HRESULT hr;
1463
1464 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1465 if(FAILED(hr))
1466 return hr;
1467
1468 if(This->bsc)
1469 detach_bsc(This->bsc);
1470
1471 This->bsc = bsc;
1472 return S_OK;
1473 }
1474
1475 static HRESULT WINAPI domdoc_load(
1476 IXMLDOMDocument2 *iface,
1477 VARIANT xmlSource,
1478 VARIANT_BOOL* isSuccessful )
1479 {
1480 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1481 LPWSTR filename = NULL;
1482 HRESULT hr = S_FALSE;
1483 IXMLDOMDocument2 *pNewDoc = NULL;
1484 IStream *pStream = NULL;
1485 xmlDocPtr xmldoc;
1486
1487 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1488
1489 *isSuccessful = VARIANT_FALSE;
1490
1491 assert( &This->node );
1492
1493 switch( V_VT(&xmlSource) )
1494 {
1495 case VT_BSTR:
1496 filename = V_BSTR(&xmlSource);
1497 break;
1498 case VT_UNKNOWN:
1499 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1500 if(hr == S_OK)
1501 {
1502 if(pNewDoc)
1503 {
1504 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1505 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1506 hr = attach_xmldoc(&This->node, xmldoc);
1507
1508 if(SUCCEEDED(hr))
1509 *isSuccessful = VARIANT_TRUE;
1510
1511 return hr;
1512 }
1513 }
1514 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1515 if(hr == S_OK)
1516 {
1517 IPersistStream *pDocStream;
1518 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1519 if(hr == S_OK)
1520 {
1521 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1522 IStream_Release(pStream);
1523 if(hr == S_OK)
1524 {
1525 *isSuccessful = VARIANT_TRUE;
1526
1527 TRACE("Using ID_IStream to load Document\n");
1528 return S_OK;
1529 }
1530 else
1531 {
1532 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1533 }
1534 }
1535 else
1536 {
1537 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1538 }
1539 }
1540 else
1541 {
1542 /* ISequentialStream */
1543 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1544 }
1545 break;
1546 default:
1547 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1548 }
1549
1550 TRACE("filename (%s)\n", debugstr_w(filename));
1551
1552 if ( filename )
1553 {
1554 hr = doread( This, filename );
1555
1556 if ( FAILED(hr) )
1557 This->error = E_FAIL;
1558 else
1559 {
1560 hr = This->error = S_OK;
1561 *isSuccessful = VARIANT_TRUE;
1562 }
1563 }
1564
1565 if(!filename || FAILED(hr)) {
1566 xmldoc = xmlNewDoc(NULL);
1567 xmldoc->_private = create_priv();
1568 hr = attach_xmldoc(&This->node, xmldoc);
1569 if(SUCCEEDED(hr))
1570 hr = S_FALSE;
1571 }
1572
1573 TRACE("ret (%d)\n", hr);
1574
1575 return hr;
1576 }
1577
1578
1579 static HRESULT WINAPI domdoc_get_readyState(
1580 IXMLDOMDocument2 *iface,
1581 LONG *value )
1582 {
1583 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1584 FIXME("(%p)->(%p)\n", This, value);
1585 return E_NOTIMPL;
1586 }
1587
1588
1589 static HRESULT WINAPI domdoc_get_parseError(
1590 IXMLDOMDocument2 *iface,
1591 IXMLDOMParseError** errorObj )
1592 {
1593 BSTR error_string = NULL;
1594 static const WCHAR err[] = {'e','r','r','o','r',0};
1595 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1596
1597 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1598
1599 if(This->error)
1600 error_string = SysAllocString(err);
1601
1602 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1603 if(!*errorObj) return E_OUTOFMEMORY;
1604 return S_OK;
1605 }
1606
1607
1608 static HRESULT WINAPI domdoc_get_url(
1609 IXMLDOMDocument2 *iface,
1610 BSTR* urlString )
1611 {
1612 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1613 FIXME("(%p)->(%p)\n", This, urlString);
1614 return E_NOTIMPL;
1615 }
1616
1617
1618 static HRESULT WINAPI domdoc_get_async(
1619 IXMLDOMDocument2 *iface,
1620 VARIANT_BOOL* isAsync )
1621 {
1622 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1623
1624 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1625 *isAsync = This->async;
1626 return S_OK;
1627 }
1628
1629
1630 static HRESULT WINAPI domdoc_put_async(
1631 IXMLDOMDocument2 *iface,
1632 VARIANT_BOOL isAsync )
1633 {
1634 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1635
1636 TRACE("(%p)->(%d)\n", This, isAsync);
1637 This->async = isAsync;
1638 return S_OK;
1639 }
1640
1641
1642 static HRESULT WINAPI domdoc_abort(
1643 IXMLDOMDocument2 *iface )
1644 {
1645 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1646 FIXME("%p\n", This);
1647 return E_NOTIMPL;
1648 }
1649
1650
1651 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1652 {
1653 UINT len;
1654 LPSTR str;
1655
1656 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
1657 str = heap_alloc( len );
1658 if ( !str )
1659 return FALSE;
1660 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
1661 *plen = len;
1662 *pstr = str;
1663 return TRUE;
1664 }
1665
1666 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
1667 static HRESULT WINAPI domdoc_loadXML(
1668 IXMLDOMDocument2 *iface,
1669 BSTR bstrXML,
1670 VARIANT_BOOL* isSuccessful )
1671 {
1672 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1673 xmlDocPtr xmldoc = NULL;
1674 char *str;
1675 int len;
1676 HRESULT hr = S_FALSE, hr2;
1677
1678 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1679
1680 assert ( &This->node );
1681
1682 if ( isSuccessful )
1683 {
1684 *isSuccessful = VARIANT_FALSE;
1685
1686 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1687 {
1688 xmldoc = doparse( str, len );
1689 heap_free( str );
1690 if ( !xmldoc )
1691 This->error = E_FAIL;
1692 else
1693 {
1694 hr = This->error = S_OK;
1695 *isSuccessful = VARIANT_TRUE;
1696 }
1697 }
1698 }
1699 if(!xmldoc)
1700 xmldoc = xmlNewDoc(NULL);
1701
1702 xmldoc->_private = create_priv();
1703 hr2 = attach_xmldoc( &This->node, xmldoc );
1704 if( FAILED(hr2) )
1705 hr = hr2;
1706
1707 return hr;
1708 }
1709
1710 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1711 int len)
1712 {
1713 DWORD written = -1;
1714
1715 if(!WriteFile(ctx, buffer, len, &written, NULL))
1716 {
1717 WARN("write error\n");
1718 return -1;
1719 }
1720 else
1721 return written;
1722 }
1723
1724 static int XMLCALL domdoc_save_closecallback(void *ctx)
1725 {
1726 return CloseHandle(ctx) ? 0 : -1;
1727 }
1728
1729 static HRESULT WINAPI domdoc_save(
1730 IXMLDOMDocument2 *iface,
1731 VARIANT destination )
1732 {
1733 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1734 HANDLE handle;
1735 xmlSaveCtxtPtr ctx;
1736 HRESULT ret = S_OK;
1737
1738 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1739 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1740
1741 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1742 {
1743 FIXME("Unhandled vt %d\n", V_VT(&destination));
1744 return S_FALSE;
1745 }
1746
1747 if(V_VT(&destination) == VT_UNKNOWN)
1748 {
1749 IUnknown *pUnk = V_UNKNOWN(&destination);
1750 IXMLDOMDocument *pDocument;
1751
1752 ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1753 if(ret == S_OK)
1754 {
1755 BSTR bXML;
1756 VARIANT_BOOL bSuccessful;
1757
1758 ret = IXMLDOMDocument_get_xml(iface, &bXML);
1759 if(ret == S_OK)
1760 {
1761 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1762
1763 SysFreeString(bXML);
1764 }
1765
1766 IXMLDOMDocument_Release(pDocument);
1767 }
1768
1769 TRACE("ret %d\n", ret);
1770
1771 return ret;
1772 }
1773
1774 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1775 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1776 if( handle == INVALID_HANDLE_VALUE )
1777 {
1778 WARN("failed to create file\n");
1779 return S_FALSE;
1780 }
1781
1782 /* disable top XML declaration */
1783 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1784 handle, NULL, XML_SAVE_NO_DECL);
1785 if (!ctx)
1786 {
1787 CloseHandle(handle);
1788 return S_FALSE;
1789 }
1790
1791 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1792 /* will close file through close callback */
1793 xmlSaveClose(ctx);
1794
1795 return ret;
1796 }
1797
1798 static HRESULT WINAPI domdoc_get_validateOnParse(
1799 IXMLDOMDocument2 *iface,
1800 VARIANT_BOOL* isValidating )
1801 {
1802 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1803
1804 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1805 *isValidating = This->validating;
1806 return S_OK;
1807 }
1808
1809
1810 static HRESULT WINAPI domdoc_put_validateOnParse(
1811 IXMLDOMDocument2 *iface,
1812 VARIANT_BOOL isValidating )
1813 {
1814 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1815
1816 TRACE("(%p)->(%d)\n", This, isValidating);
1817 This->validating = isValidating;
1818 return S_OK;
1819 }
1820
1821
1822 static HRESULT WINAPI domdoc_get_resolveExternals(
1823 IXMLDOMDocument2 *iface,
1824 VARIANT_BOOL* isResolving )
1825 {
1826 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1827
1828 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1829 *isResolving = This->resolving;
1830 return S_OK;
1831 }
1832
1833
1834 static HRESULT WINAPI domdoc_put_resolveExternals(
1835 IXMLDOMDocument2 *iface,
1836 VARIANT_BOOL isResolving )
1837 {
1838 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1839
1840 TRACE("(%p)->(%d)\n", This, isResolving);
1841 This->resolving = isResolving;
1842 return S_OK;
1843 }
1844
1845
1846 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1847 IXMLDOMDocument2 *iface,
1848 VARIANT_BOOL* isPreserving )
1849 {
1850 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1851
1852 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1853 *isPreserving = This->preserving;
1854 return S_OK;
1855 }
1856
1857
1858 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1859 IXMLDOMDocument2 *iface,
1860 VARIANT_BOOL isPreserving )
1861 {
1862 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1863
1864 TRACE("(%p)->(%d)\n", This, isPreserving);
1865 This->preserving = isPreserving;
1866 return S_OK;
1867 }
1868
1869
1870 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1871 IXMLDOMDocument2 *iface,
1872 VARIANT readyStateChangeSink )
1873 {
1874 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1875 FIXME("%p\n", This);
1876 return E_NOTIMPL;
1877 }
1878
1879
1880 static HRESULT WINAPI domdoc_put_onDataAvailable(
1881 IXMLDOMDocument2 *iface,
1882 VARIANT onDataAvailableSink )
1883 {
1884 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1885 FIXME("%p\n", This);
1886 return E_NOTIMPL;
1887 }
1888
1889 static HRESULT WINAPI domdoc_put_onTransformNode(
1890 IXMLDOMDocument2 *iface,
1891 VARIANT onTransformNodeSink )
1892 {
1893 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1894 FIXME("%p\n", This);
1895 return E_NOTIMPL;
1896 }
1897
1898 static HRESULT WINAPI domdoc_get_namespaces(
1899 IXMLDOMDocument2* iface,
1900 IXMLDOMSchemaCollection** schemaCollection )
1901 {
1902 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1903 FIXME("(%p)->(%p)\n", This, schemaCollection);
1904 return E_NOTIMPL;
1905 }
1906
1907 static HRESULT WINAPI domdoc_get_schemas(
1908 IXMLDOMDocument2* iface,
1909 VARIANT* var1 )
1910 {
1911 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1912 HRESULT hr = S_FALSE;
1913 IXMLDOMSchemaCollection *cur_schema = This->schema;
1914
1915 TRACE("(%p)->(%p)\n", This, var1);
1916
1917 VariantInit(var1); /* Test shows we don't call VariantClear here */
1918 V_VT(var1) = VT_NULL;
1919
1920 if(cur_schema)
1921 {
1922 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1923 if(SUCCEEDED(hr))
1924 V_VT(var1) = VT_DISPATCH;
1925 }
1926 return hr;
1927 }
1928
1929 static HRESULT WINAPI domdoc_putref_schemas(
1930 IXMLDOMDocument2* iface,
1931 VARIANT var1)
1932 {
1933 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1934 HRESULT hr = E_FAIL;
1935 IXMLDOMSchemaCollection *new_schema = NULL;
1936
1937 FIXME("(%p): semi-stub\n", This);
1938 switch(V_VT(&var1))
1939 {
1940 case VT_UNKNOWN:
1941 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1942 break;
1943
1944 case VT_DISPATCH:
1945 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1946 break;
1947
1948 case VT_NULL:
1949 case VT_EMPTY:
1950 hr = S_OK;
1951 break;
1952
1953 default:
1954 WARN("Can't get schema from vt %x\n", V_VT(&var1));
1955 }
1956
1957 if(SUCCEEDED(hr))
1958 {
1959 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1960 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1961 }
1962
1963 return hr;
1964 }
1965
1966 static HRESULT WINAPI domdoc_validate(
1967 IXMLDOMDocument2* iface,
1968 IXMLDOMParseError** err)
1969 {
1970 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1971 FIXME("(%p)->(%p)\n", This, err);
1972 return E_NOTIMPL;
1973 }
1974
1975 static HRESULT WINAPI domdoc_setProperty(
1976 IXMLDOMDocument2* iface,
1977 BSTR p,
1978 VARIANT var)
1979 {
1980 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1981
1982 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1983
1984 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1985 {
1986 VARIANT varStr;
1987 HRESULT hr;
1988 BSTR bstr;
1989
1990 V_VT(&varStr) = VT_EMPTY;
1991 if (V_VT(&var) != VT_BSTR)
1992 {
1993 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1994 return hr;
1995 bstr = V_BSTR(&varStr);
1996 }
1997 else
1998 bstr = V_BSTR(&var);
1999
2000 hr = S_OK;
2001 if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
2002 This->bUseXPath = TRUE;
2003 else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
2004 This->bUseXPath = FALSE;
2005 else
2006 hr = E_FAIL;
2007
2008 VariantClear(&varStr);
2009 return hr;
2010 }
2011
2012 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2013 return E_FAIL;
2014 }
2015
2016 static HRESULT WINAPI domdoc_getProperty(
2017 IXMLDOMDocument2* iface,
2018 BSTR p,
2019 VARIANT* var)
2020 {
2021 domdoc *This = impl_from_IXMLDOMDocument2( iface );
2022
2023 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2024
2025 if (var == NULL)
2026 return E_INVALIDARG;
2027 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
2028 {
2029 V_VT(var) = VT_BSTR;
2030 if (This->bUseXPath)
2031 V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
2032 else
2033 V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
2034 return S_OK;
2035 }
2036
2037 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2038 return E_FAIL;
2039 }
2040
2041 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
2042 {
2043 domdoc_QueryInterface,
2044 domdoc_AddRef,
2045 domdoc_Release,
2046 domdoc_GetTypeInfoCount,
2047 domdoc_GetTypeInfo,
2048 domdoc_GetIDsOfNames,
2049 domdoc_Invoke,
2050 domdoc_get_nodeName,
2051 domdoc_get_nodeValue,
2052 domdoc_put_nodeValue,
2053 domdoc_get_nodeType,
2054 domdoc_get_parentNode,
2055 domdoc_get_childNodes,
2056 domdoc_get_firstChild,
2057 domdoc_get_lastChild,
2058 domdoc_get_previousSibling,
2059 domdoc_get_nextSibling,
2060 domdoc_get_attributes,
2061 domdoc_insertBefore,
2062 domdoc_replaceChild,
2063 domdoc_removeChild,
2064 domdoc_appendChild,
2065 domdoc_hasChildNodes,
2066 domdoc_get_ownerDocument,
2067 domdoc_cloneNode,
2068 domdoc_get_nodeTypeString,
2069 domdoc_get_text,
2070 domdoc_put_text,
2071 domdoc_get_specified,
2072 domdoc_get_definition,
2073 domdoc_get_nodeTypedValue,
2074 domdoc_put_nodeTypedValue,
2075 domdoc_get_dataType,
2076 domdoc_put_dataType,
2077 domdoc_get_xml,
2078 domdoc_transformNode,
2079 domdoc_selectNodes,
2080 domdoc_selectSingleNode,
2081 domdoc_get_parsed,
2082 domdoc_get_namespaceURI,
2083 domdoc_get_prefix,
2084 domdoc_get_baseName,
2085 domdoc_transformNodeToObject,
2086 domdoc_get_doctype,
2087 domdoc_get_implementation,
2088 domdoc_get_documentElement,
2089 domdoc_put_documentElement,
2090 domdoc_createElement,
2091 domdoc_createDocumentFragment,
2092 domdoc_createTextNode,
2093 domdoc_createComment,
2094 domdoc_createCDATASection,
2095 domdoc_createProcessingInstruction,
2096 domdoc_createAttribute,
2097 domdoc_createEntityReference,
2098 domdoc_getElementsByTagName,
2099 domdoc_createNode,
2100 domdoc_nodeFromID,
2101 domdoc_load,
2102 domdoc_get_readyState,
2103 domdoc_get_parseError,
2104 domdoc_get_url,
2105 domdoc_get_async,
2106 domdoc_put_async,
2107 domdoc_abort,
2108 domdoc_loadXML,
2109 domdoc_save,
2110 domdoc_get_validateOnParse,
2111 domdoc_put_validateOnParse,
2112 domdoc_get_resolveExternals,
2113 domdoc_put_resolveExternals,
2114 domdoc_get_preserveWhiteSpace,
2115 domdoc_put_preserveWhiteSpace,
2116 domdoc_put_onReadyStateChange,
2117 domdoc_put_onDataAvailable,
2118 domdoc_put_onTransformNode,
2119 domdoc_get_namespaces,
2120 domdoc_get_schemas,
2121 domdoc_putref_schemas,
2122 domdoc_validate,
2123 domdoc_setProperty,
2124 domdoc_getProperty
2125 };
2126
2127 /* xmldoc implementation of IObjectWithSite */
2128 static HRESULT WINAPI
2129 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2130 {
2131 domdoc *This = impl_from_IObjectWithSite(iface);
2132 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2133 }
2134
2135 static ULONG WINAPI
2136 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2137 {
2138 domdoc *This = impl_from_IObjectWithSite(iface);
2139 return IXMLDocument_AddRef((IXMLDocument *)This);
2140 }
2141
2142 static ULONG WINAPI
2143 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2144 {
2145 domdoc *This = impl_from_IObjectWithSite(iface);
2146 return IXMLDocument_Release((IXMLDocument *)This);
2147 }
2148
2149 static HRESULT WINAPI
2150 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2151 {
2152 domdoc *This = impl_from_IObjectWithSite(iface);
2153
2154 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2155
2156 if ( !This->site )
2157 return E_FAIL;
2158
2159 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2160 }
2161
2162 static HRESULT WINAPI
2163 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2164 {
2165 domdoc *This = impl_from_IObjectWithSite(iface);
2166
2167 TRACE("(%p)->(%p)\n", iface, punk);
2168
2169 if(!punk)
2170 {
2171 if(This->site)
2172 {
2173 IUnknown_Release( This->site );
2174 This->site = NULL;
2175 }
2176
2177 return S_OK;
2178 }
2179
2180 if ( punk )
2181 IUnknown_AddRef( punk );
2182
2183 if(This->site)
2184 IUnknown_Release( This->site );
2185
2186 This->site = punk;
2187
2188 return S_OK;
2189 }
2190
2191 static const IObjectWithSiteVtbl domdocObjectSite =
2192 {
2193 xmldoc_ObjectWithSite_QueryInterface,
2194 xmldoc_ObjectWithSite_AddRef,
2195 xmldoc_ObjectWithSite_Release,
2196 xmldoc_SetSite,
2197 xmldoc_GetSite,
2198 };
2199
2200 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2201 {
2202 domdoc *This = impl_from_IObjectSafety(iface);
2203 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2204 }
2205
2206 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2207 {
2208 domdoc *This = impl_from_IObjectSafety(iface);
2209 return IXMLDocument_AddRef((IXMLDocument *)This);
2210 }
2211
2212 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2213 {
2214 domdoc *This = impl_from_IObjectSafety(iface);
2215 return IXMLDocument_Release((IXMLDocument *)This);
2216 }
2217
2218 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2219
2220 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2221 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2222 {
2223 domdoc *This = impl_from_IObjectSafety(iface);
2224
2225 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2226
2227 if(!pdwSupportedOptions || !pdwEnabledOptions)
2228 return E_POINTER;
2229
2230 *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
2231 *pdwEnabledOptions = This->safeopt;
2232
2233 return S_OK;
2234 }
2235
2236 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2237 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2238 {
2239 domdoc *This = impl_from_IObjectSafety(iface);
2240 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2241
2242 if ((dwOptionSetMask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
2243 return E_FAIL;
2244
2245 This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
2246 return S_OK;
2247 }
2248
2249 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2250 xmldoc_Safety_QueryInterface,
2251 xmldoc_Safety_AddRef,
2252 xmldoc_Safety_Release,
2253 xmldoc_Safety_GetInterfaceSafetyOptions,
2254 xmldoc_Safety_SetInterfaceSafetyOptions
2255 };
2256
2257
2258 static const tid_t domdoc_iface_tids[] = {
2259 IXMLDOMNode_tid,
2260 IXMLDOMDocument_tid,
2261 IXMLDOMDocument2_tid,
2262 0
2263 };
2264 static dispex_static_data_t domdoc_dispex = {
2265 NULL,
2266 IXMLDOMDocument2_tid,
2267 NULL,
2268 domdoc_iface_tids
2269 };
2270
2271 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2272 {
2273 domdoc *doc;
2274
2275 doc = heap_alloc( sizeof (*doc) );
2276 if( !doc )
2277 return E_OUTOFMEMORY;
2278
2279 doc->lpVtbl = &domdoc_vtbl;
2280 doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2281 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2282 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2283 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2284 doc->ref = 1;
2285 doc->async = VARIANT_TRUE;
2286 doc->validating = 0;
2287 doc->resolving = 0;
2288 doc->preserving = 0;
2289 doc->bUseXPath = FALSE;
2290 doc->error = S_OK;
2291 doc->schema = NULL;
2292 doc->stream = NULL;
2293 doc->site = NULL;
2294 doc->safeopt = 0;
2295 doc->bsc = NULL;
2296
2297 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2298
2299 *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2300
2301 TRACE("returning iface %p\n", *document);
2302 return S_OK;
2303 }
2304
2305 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2306 {
2307 xmlDocPtr xmldoc;
2308 HRESULT hr;
2309
2310 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2311
2312 xmldoc = xmlNewDoc(NULL);
2313 if(!xmldoc)
2314 return E_OUTOFMEMORY;
2315
2316 xmldoc->_private = create_priv();
2317
2318 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2319 if(FAILED(hr))
2320 xmlFreeDoc(xmldoc);
2321
2322 return hr;
2323 }
2324
2325 IUnknown* create_domdoc( xmlNodePtr document )
2326 {
2327 HRESULT hr;
2328 LPVOID pObj = NULL;
2329
2330 TRACE("(%p)\n", document);
2331
2332 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2333 if (FAILED(hr))
2334 return NULL;
2335
2336 return pObj;
2337 }
2338
2339 #else
2340
2341 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2342 {
2343 MESSAGE("This program tried to use a DOMDocument object, but\n"
2344 "libxml2 support was not present at compile time.\n");
2345 return E_NOTIMPL;
2346 }
2347
2348 #endif