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