xref: /reactos/dll/win32/msxml3/xmlview.c (revision f04935d8)
1 /*
2  * Copyright 2012 Piotr Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "config.h"
20 
21 #include <stdarg.h>
22 
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 
26 #ifdef HAVE_LIBXML2
27 #include <libxml/parser.h>
28 #endif
29 
30 #include "windef.h"
31 #include "winbase.h"
32 #include "ole2.h"
33 #include "msxml6.h"
34 #ifdef __REACTOS__
35 #include <wingdi.h>
36 #endif
37 #include "mshtml.h"
38 #include "mshtmhst.h"
39 #include "perhist.h"
40 #include "docobj.h"
41 
42 #include "wine/debug.h"
43 
44 #include "msxml_private.h"
45 
46 #ifdef HAVE_LIBXML2
47 
48 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
49 
50 typedef struct
51 {
52     IPersistMoniker IPersistMoniker_iface;
53     IPersistHistory IPersistHistory_iface;
54     IOleCommandTarget IOleCommandTarget_iface;
55     IOleObject IOleObject_iface;
56 
57     LONG ref;
58 
59     IUnknown *html_doc;
60     IMoniker *mon;
61 } XMLView;
62 
63 typedef struct
64 {
65     IMoniker IMoniker_iface;
66     LONG ref;
67     IMoniker *mon;
68 
69     IStream *stream;
70 } Moniker;
71 
72 typedef struct
73 {
74     IBindStatusCallback IBindStatusCallback_iface;
75     LONG ref;
76     IBindStatusCallback *bsc;
77 
78     IMoniker *mon;
79     IStream *stream;
80 } BindStatusCallback;
81 
82 typedef struct
83 {
84     IBinding IBinding_iface;
85     LONG ref;
86     IBinding *binding;
87 } Binding;
88 
89 static inline Binding* impl_from_IBinding(IBinding *iface)
90 {
91     return CONTAINING_RECORD(iface, Binding, IBinding_iface);
92 }
93 
94 static HRESULT WINAPI XMLView_Binding_QueryInterface(
95         IBinding *iface, REFIID riid, void **ppvObject)
96 {
97     Binding *This = impl_from_IBinding(iface);
98 
99     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
100 
101     if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IBinding)) {
102         *ppvObject = iface;
103         IBinding_AddRef(iface);
104         return S_OK;
105     }
106 
107     *ppvObject = NULL;
108     return E_NOINTERFACE;
109 }
110 
111 static ULONG WINAPI XMLView_Binding_AddRef(IBinding *iface)
112 {
113     Binding *This = impl_from_IBinding(iface);
114     LONG ref = InterlockedIncrement(&This->ref);
115 
116     TRACE("(%p)->(%d)\n", This, ref);
117 
118     return ref;
119 }
120 
121 static ULONG WINAPI XMLView_Binding_Release(IBinding *iface)
122 {
123     Binding *This = impl_from_IBinding(iface);
124     ULONG ref = InterlockedDecrement(&This->ref);
125 
126     TRACE("(%p)->(%d)\n", This, ref);
127 
128     if(!ref) {
129         IBinding_Release(This->binding);
130         heap_free(This);
131     }
132     return ref;
133 }
134 
135 static HRESULT WINAPI XMLView_Binding_Abort(IBinding *iface)
136 {
137     Binding *This = impl_from_IBinding(iface);
138     TRACE("(%p)\n", This);
139 
140     return IBinding_Abort(This->binding);
141 }
142 
143 static HRESULT WINAPI XMLView_Binding_Suspend(IBinding *iface)
144 {
145     Binding *This = impl_from_IBinding(iface);
146     FIXME("(%p)\n", This);
147     return E_NOTIMPL;
148 }
149 
150 static HRESULT WINAPI XMLView_Binding_Resume(IBinding *iface)
151 {
152     Binding *This = impl_from_IBinding(iface);
153     FIXME("(%p)\n", This);
154     return E_NOTIMPL;
155 }
156 
157 static HRESULT WINAPI XMLView_Binding_SetPriority(
158         IBinding *iface, LONG nPriority)
159 {
160     Binding *This = impl_from_IBinding(iface);
161     TRACE("(%p)->(%d)\n", This, nPriority);
162 
163     return IBinding_SetPriority(This->binding, nPriority);
164 }
165 
166 static HRESULT WINAPI XMLView_Binding_GetPriority(
167         IBinding *iface, LONG *pnPriority)
168 {
169     Binding *This = impl_from_IBinding(iface);
170     TRACE("(%p)->(%p)\n", This, pnPriority);
171 
172     return IBinding_GetPriority(This->binding, pnPriority);
173 }
174 
175 static HRESULT WINAPI XMLView_Binding_GetBindResult(IBinding *iface,
176         CLSID *pclsidProtocol, DWORD *pdwResult, LPOLESTR *pszResult,
177         DWORD *pdwReserved)
178 {
179     Binding *This = impl_from_IBinding(iface);
180     FIXME("(%p)->(%s %p %p %p)\n", This, debugstr_guid(pclsidProtocol),
181             pdwResult, pszResult, pdwReserved);
182     return E_NOTIMPL;
183 }
184 
185 static IBindingVtbl XMLView_BindingVtbl = {
186     XMLView_Binding_QueryInterface,
187     XMLView_Binding_AddRef,
188     XMLView_Binding_Release,
189     XMLView_Binding_Abort,
190     XMLView_Binding_Suspend,
191     XMLView_Binding_Resume,
192     XMLView_Binding_SetPriority,
193     XMLView_Binding_GetPriority,
194     XMLView_Binding_GetBindResult
195 };
196 
197 static inline HRESULT XMLView_Binding_Create(IBinding *binding, IBinding **ret)
198 {
199     Binding *bind;
200 
201     bind = heap_alloc_zero(sizeof(Binding));
202     if(!bind)
203         return E_OUTOFMEMORY;
204 
205     bind->IBinding_iface.lpVtbl = &XMLView_BindingVtbl;
206     bind->ref = 1;
207 
208     bind->binding = binding;
209     IBinding_AddRef(binding);
210 
211     *ret = &bind->IBinding_iface;
212     return S_OK;
213 }
214 
215 static inline BindStatusCallback* impl_from_IBindStatusCallback(
216         IBindStatusCallback *iface)
217 {
218     return CONTAINING_RECORD(iface, BindStatusCallback,
219             IBindStatusCallback_iface);
220 }
221 
222 static HRESULT WINAPI XMLView_BindStatusCallback_QueryInterface(
223         IBindStatusCallback *iface, REFIID riid, void **ppvObject)
224 {
225     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
226 
227     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
228 
229     if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IBindStatusCallback)) {
230         *ppvObject = iface;
231         IBindStatusCallback_AddRef(iface);
232         return S_OK;
233     }
234 
235     *ppvObject = NULL;
236     return E_NOINTERFACE;
237 }
238 
239 static ULONG WINAPI XMLView_BindStatusCallback_AddRef(
240         IBindStatusCallback *iface)
241 {
242     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
243     LONG ref = InterlockedIncrement(&This->ref);
244 
245     TRACE("(%p)->(%d)\n", This, ref);
246 
247     return ref;
248 }
249 
250 static ULONG WINAPI XMLView_BindStatusCallback_Release(
251         IBindStatusCallback *iface)
252 {
253     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
254     ULONG ref = InterlockedDecrement(&This->ref);
255 
256     TRACE("(%p)->(%d)\n", This, ref);
257 
258     if(!ref) {
259         if(This->stream)
260             IStream_Release(This->stream);
261         IBindStatusCallback_Release(This->bsc);
262         IMoniker_Release(This->mon);
263         heap_free(This);
264     }
265     return ref;
266 }
267 
268 static HRESULT WINAPI XMLView_BindStatusCallback_OnStartBinding(
269         IBindStatusCallback *iface, DWORD dwReserved, IBinding *pib)
270 {
271     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
272     IBinding *binding;
273     HRESULT hres;
274 
275     TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
276 
277     hres = XMLView_Binding_Create(pib, &binding);
278     if(FAILED(hres)) {
279         IBinding_Abort(pib);
280         return hres;
281     }
282 
283     hres = IBindStatusCallback_OnStartBinding(This->bsc, dwReserved, binding);
284     if(FAILED(hres)) {
285         IBinding_Abort(binding);
286         return hres;
287     }
288 
289     IBinding_Release(binding);
290     return hres;
291 }
292 
293 static HRESULT WINAPI XMLView_BindStatusCallback_GetPriority(
294         IBindStatusCallback *iface, LONG *pnPriority)
295 {
296     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
297     FIXME("(%p)->(%p)\n", This, pnPriority);
298     return E_NOTIMPL;
299 }
300 
301 static HRESULT WINAPI XMLView_BindStatusCallback_OnLowResource(
302         IBindStatusCallback *iface, DWORD reserved)
303 {
304     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
305     FIXME("(%p)->(%x)\n", This, reserved);
306     return E_NOTIMPL;
307 }
308 
309 static HRESULT WINAPI XMLView_BindStatusCallback_OnProgress(
310         IBindStatusCallback *iface, ULONG ulProgress, ULONG ulProgressMax,
311         ULONG ulStatusCode, LPCWSTR szStatusText)
312 {
313     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
314     TRACE("(%p)->(%d %d %x %s)\n", This, ulProgress, ulProgressMax,
315             ulStatusCode, debugstr_w(szStatusText));
316 
317     switch(ulStatusCode) {
318     case BINDSTATUS_BEGINDOWNLOADDATA:
319         return IBindStatusCallback_OnProgress(This->bsc, ulProgress,
320                 ulProgressMax, ulStatusCode, szStatusText);
321     case BINDSTATUS_MIMETYPEAVAILABLE:
322         return S_OK;
323     default:
324         FIXME("ulStatusCode: %d\n", ulStatusCode);
325         return E_NOTIMPL;
326     }
327 }
328 
329 static HRESULT WINAPI XMLView_BindStatusCallback_OnStopBinding(
330         IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
331 {
332     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
333     TRACE("(%p)->(%x %s)\n", This, hresult, debugstr_w(szError));
334     return IBindStatusCallback_OnStopBinding(This->bsc, hresult, szError);
335 }
336 
337 static HRESULT WINAPI XMLView_BindStatusCallback_GetBindInfo(
338         IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
339 {
340     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
341     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
342     return IBindStatusCallback_GetBindInfo(This->bsc, grfBINDF, pbindinfo);
343 }
344 
345 static inline HRESULT report_data(BindStatusCallback *This)
346 {
347     FORMATETC formatetc = {0, NULL, 1, -1, TYMED_ISTREAM};
348     STGMEDIUM stgmedium;
349     LARGE_INTEGER off;
350     ULARGE_INTEGER size;
351     HRESULT hres;
352 
353     off.QuadPart = 0;
354     hres = IStream_Seek(This->stream, off, STREAM_SEEK_CUR, &size);
355     if(FAILED(hres))
356         return hres;
357 
358     hres = IStream_Seek(This->stream, off, STREAM_SEEK_SET, NULL);
359     if(FAILED(hres))
360         return hres;
361 
362     stgmedium.tymed = TYMED_ISTREAM;
363     stgmedium.u.pstm = This->stream;
364     stgmedium.pUnkForRelease = NULL;
365 
366     hres = IBindStatusCallback_OnDataAvailable(This->bsc,
367             BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION,
368             size.u.LowPart, &formatetc, &stgmedium);
369 
370     IStream_Release(This->stream);
371     This->stream = NULL;
372     return hres;
373 }
374 
375 static inline HRESULT display_error_page(BindStatusCallback *This)
376 {
377     FIXME("Error page not implemented yet.\n");
378     return report_data(This);
379 }
380 
381 static inline HRESULT handle_xml_load(BindStatusCallback *This)
382 {
383     static const WCHAR selectW[] = {'p','r','o','c','e','s','s','i','n','g','-',
384         'i','n','s','t','r','u','c','t','i','o','n','(','\'','x','m','l',
385         '-','s','t','y','l','e','s','h','e','e','t','\'',')',0};
386     static const WCHAR hrefW[] = {'h','r','e','f','=',0};
387 
388     IXMLDOMDocument3 *xml = NULL, *xsl = NULL;
389     IXMLDOMNode *stylesheet;
390     IBindCtx *pbc;
391     IMoniker *mon;
392     LPOLESTR xsl_url;
393     LARGE_INTEGER off;
394     VARIANT_BOOL succ;
395     VARIANT var;
396     WCHAR *href = NULL, *p;
397     BSTR bstr;
398     HRESULT hres;
399 
400     off.QuadPart = 0;
401     hres = IStream_Seek(This->stream, off, STREAM_SEEK_SET, NULL);
402     if(FAILED(hres))
403         return display_error_page(This);
404 
405     hres = DOMDocument_create(MSXML_DEFAULT, (void**)&xml);
406     if(FAILED(hres))
407         return display_error_page(This);
408 
409     V_VT(&var) = VT_UNKNOWN;
410     V_UNKNOWN(&var) = (IUnknown*)This->stream;
411     hres = IXMLDOMDocument3_load(xml, var, &succ);
412     if(FAILED(hres) || !succ) {
413         IXMLDOMDocument3_Release(xml);
414         return display_error_page(This);
415     }
416     V_VT(&var) = VT_EMPTY;
417 
418     bstr = SysAllocString(selectW);
419     hres = IXMLDOMDocument3_selectSingleNode(xml, bstr, &stylesheet);
420     SysFreeString(bstr);
421     if(hres != S_OK) {
422         IXMLDOMDocument3_Release(xml);
423         return display_error_page(This);
424     }
425 
426     hres = IXMLDOMNode_get_nodeValue(stylesheet, &var);
427     IXMLDOMNode_Release(stylesheet);
428     if(SUCCEEDED(hres) && V_VT(&var)!=VT_BSTR) {
429         FIXME("Variant type %d not supported\n", V_VT(&var));
430         VariantClear(&var);
431         hres = E_FAIL;
432     }
433     if(FAILED(hres)) {
434         IXMLDOMDocument3_Release(xml);
435         return display_error_page(This);
436     }
437 
438     /* TODO: fix parsing processing instruction value */
439     if((p = strstrW(V_BSTR(&var), hrefW))) {
440         p += ARRAY_SIZE(hrefW) - 1;
441         if(*p!='\'' && *p!='\"') p = NULL;
442         else {
443             href = p+1;
444             p = strchrW(href, *p);
445         }
446     }
447     if(p) {
448         *p = 0;
449     } else {
450         VariantClear(&var);
451         IXMLDOMDocument3_Release(xml);
452         return display_error_page(This);
453     }
454 
455     hres = CreateURLMonikerEx(This->mon, href, &mon, 0);
456     VariantClear(&var);
457     if(FAILED(hres)) {
458         IXMLDOMDocument3_Release(xml);
459         return display_error_page(This);
460     }
461 
462     hres = CreateBindCtx(0, &pbc);
463     if(SUCCEEDED(hres)) {
464         hres = IMoniker_GetDisplayName(mon, pbc, NULL, &xsl_url);
465         IMoniker_Release(mon);
466         IBindCtx_Release(pbc);
467     }
468     if(FAILED(hres)) {
469         IXMLDOMDocument3_Release(xml);
470         return display_error_page(This);
471     }
472 
473     V_VT(&var) = VT_BSTR;
474     V_BSTR(&var) = SysAllocString(xsl_url);
475     CoTaskMemFree(xsl_url);
476     if(!V_BSTR(&var)) {
477         IXMLDOMDocument3_Release(xml);
478         return display_error_page(This);
479     }
480 
481     hres = DOMDocument_create(MSXML_DEFAULT, (void**)&xsl);
482     if(FAILED(hres)) {
483         VariantClear(&var);
484         IXMLDOMDocument3_Release(xml);
485         return display_error_page(This);
486     }
487 
488     /* TODO: do the binding asynchronously */
489     hres = IXMLDOMDocument3_load(xsl, var, &succ);
490     VariantClear(&var);
491     if(FAILED(hres) || !succ) {
492         IXMLDOMDocument3_Release(xsl);
493         IXMLDOMDocument3_Release(xml);
494         return display_error_page(This);
495     }
496 
497     hres = IXMLDOMDocument3_transformNode(xml, (IXMLDOMNode*)xsl, &bstr);
498     IXMLDOMDocument3_Release(xsl);
499     IXMLDOMDocument3_Release(xml);
500     if(FAILED(hres))
501         return display_error_page(This);
502 
503     hres = IStream_Seek(This->stream, off, STREAM_SEEK_SET, NULL);
504     if(FAILED(hres)) {
505         SysFreeString(bstr);
506         return display_error_page(This);
507     }
508 
509     hres = IStream_Write(This->stream, (BYTE*)bstr,
510             SysStringLen(bstr)*sizeof(WCHAR), NULL);
511     SysFreeString(bstr);
512     if(FAILED(hres))
513         return display_error_page(This);
514 
515     return report_data(This);
516 }
517 
518 static HRESULT WINAPI XMLView_BindStatusCallback_OnDataAvailable(
519         IBindStatusCallback *iface, DWORD grfBSCF, DWORD dwSize,
520         FORMATETC *pformatetc, STGMEDIUM *pstgmed)
521 {
522     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
523     char buf[1024];
524     DWORD size;
525     HRESULT hres;
526 
527     TRACE("(%p)->(%x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
528 
529     if(!This->stream)
530         return E_FAIL;
531 
532     do {
533         hres = IStream_Read(pstgmed->u.pstm, buf, sizeof(buf), &size);
534         IStream_Write(This->stream, buf, size, &size);
535     } while(hres==S_OK && size);
536 
537     if(FAILED(hres) && hres!=E_PENDING)
538         return hres;
539     if(hres != S_FALSE)
540         return S_OK;
541 
542     return handle_xml_load(This);
543 }
544 
545 static HRESULT WINAPI XMLView_BindStatusCallback_OnObjectAvailable(
546         IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
547 {
548     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
549     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
550     return E_NOTIMPL;
551 }
552 
553 static IBindStatusCallbackVtbl XMLView_BindStatusCallbackVtbl = {
554     XMLView_BindStatusCallback_QueryInterface,
555     XMLView_BindStatusCallback_AddRef,
556     XMLView_BindStatusCallback_Release,
557     XMLView_BindStatusCallback_OnStartBinding,
558     XMLView_BindStatusCallback_GetPriority,
559     XMLView_BindStatusCallback_OnLowResource,
560     XMLView_BindStatusCallback_OnProgress,
561     XMLView_BindStatusCallback_OnStopBinding,
562     XMLView_BindStatusCallback_GetBindInfo,
563     XMLView_BindStatusCallback_OnDataAvailable,
564     XMLView_BindStatusCallback_OnObjectAvailable
565 };
566 
567 static inline HRESULT XMLView_BindStatusCallback_Create(IBindStatusCallback *bsc_html,
568         IMoniker *mon, IStream *stream, IBindStatusCallback **ret)
569 {
570     BindStatusCallback *bsc;
571 
572     bsc = heap_alloc_zero(sizeof(BindStatusCallback));
573     if(!bsc)
574         return E_OUTOFMEMORY;
575 
576     bsc->IBindStatusCallback_iface.lpVtbl = &XMLView_BindStatusCallbackVtbl;
577     bsc->ref = 1;
578 
579     bsc->bsc = bsc_html;
580     IBindStatusCallback_AddRef(bsc_html);
581     bsc->stream = stream;
582     IStream_AddRef(bsc->stream);
583     bsc->mon = mon;
584     IMoniker_AddRef(mon);
585 
586     *ret = &bsc->IBindStatusCallback_iface;
587     return S_OK;
588 }
589 
590 static inline Moniker* impl_from_IMoniker(IMoniker *iface)
591 {
592     return CONTAINING_RECORD(iface, Moniker, IMoniker_iface);
593 }
594 
595 static HRESULT WINAPI XMLView_Moniker_QueryInterface(
596         IMoniker *iface, REFIID riid, void **ppvObject)
597 {
598     Moniker *This = impl_from_IMoniker(iface);
599 
600     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
601 
602     if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IPersist)
603             || IsEqualGUID(riid, &IID_IPersistStream) || IsEqualGUID(riid, &IID_IMoniker)) {
604         *ppvObject = iface;
605         IMoniker_AddRef(iface);
606         return S_OK;
607     }
608 
609     *ppvObject = NULL;
610     return E_NOINTERFACE;
611 }
612 
613 static ULONG WINAPI XMLView_Moniker_AddRef(IMoniker *iface)
614 {
615     Moniker *This = impl_from_IMoniker(iface);
616     LONG ref = InterlockedIncrement(&This->ref);
617 
618     TRACE("(%p)->(%d)\n", This, ref);
619 
620     return ref;
621 }
622 
623 static ULONG WINAPI XMLView_Moniker_Release(IMoniker *iface)
624 {
625     Moniker *This = impl_from_IMoniker(iface);
626     ULONG ref = InterlockedDecrement(&This->ref);
627 
628     TRACE("(%p)->(%d)\n", This, ref);
629 
630     if(!ref) {
631         IMoniker_Release(This->mon);
632         heap_free(This);
633     }
634     return ref;
635 }
636 
637 static HRESULT WINAPI XMLView_Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
638 {
639     Moniker *This = impl_from_IMoniker(iface);
640     FIXME("(%p)->(%p)\n", This, pClassID);
641     return E_NOTIMPL;
642 }
643 
644 static HRESULT WINAPI XMLView_Moniker_IsDirty(IMoniker *iface)
645 {
646     Moniker *This = impl_from_IMoniker(iface);
647     FIXME("(%p)\n", This);
648     return E_NOTIMPL;
649 }
650 
651 static HRESULT WINAPI XMLView_Moniker_Load(IMoniker *iface, IStream *pStm)
652 {
653     Moniker *This = impl_from_IMoniker(iface);
654     FIXME("(%p)->(%p)\n", This, pStm);
655     return E_NOTIMPL;
656 }
657 
658 static HRESULT WINAPI XMLView_Moniker_Save(IMoniker *iface,
659         IStream *pStm, BOOL fClearDirty)
660 {
661     Moniker *This = impl_from_IMoniker(iface);
662     FIXME("(%p)->(%p %x)\n", This, pStm, fClearDirty);
663     return E_NOTIMPL;
664 }
665 
666 static HRESULT WINAPI XMLView_Moniker_GetSizeMax(
667         IMoniker *iface, ULARGE_INTEGER *pcbSize)
668 {
669     Moniker *This = impl_from_IMoniker(iface);
670     FIXME("(%p)->(%p)\n", This, pcbSize);
671     return E_NOTIMPL;
672 }
673 
674 static HRESULT WINAPI XMLView_Moniker_BindToObject(IMoniker *iface, IBindCtx *pbc,
675         IMoniker *pmkToLeft, REFIID riidResult, void **ppvResult)
676 {
677     Moniker *This = impl_from_IMoniker(iface);
678     FIXME("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft,
679             debugstr_guid(riidResult), ppvResult);
680     return E_NOTIMPL;
681 }
682 
683 static HRESULT WINAPI XMLView_Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc,
684         IMoniker *pmkToLeft, REFIID riid, void **ppvObj)
685 {
686     Moniker *This = impl_from_IMoniker(iface);
687 
688     TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObj);
689 
690     if(IsEqualGUID(riid, &IID_IStream)) {
691         if(!This->stream)
692             return E_FAIL;
693 
694         *ppvObj = This->stream;
695         This->stream = NULL;
696         return S_ASYNCHRONOUS;
697     }
698 
699     return E_NOTIMPL;
700 }
701 
702 static HRESULT WINAPI XMLView_Moniker_Reduce(IMoniker *iface, IBindCtx *pbc,
703         DWORD dwReduceHowFar, IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
704 {
705     Moniker *This = impl_from_IMoniker(iface);
706     FIXME("(%p)->(%p %d %p %p)\n", This, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
707     return E_NOTIMPL;
708 }
709 
710 static HRESULT WINAPI XMLView_Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
711         BOOL fOnlyIfNotGeneric, IMoniker **ppmkComposite)
712 {
713     Moniker *This = impl_from_IMoniker(iface);
714     FIXME("(%p)->(%p %x %p)\n", This, pmkRight, fOnlyIfNotGeneric, ppmkComposite);
715     return E_NOTIMPL;
716 }
717 
718 static HRESULT WINAPI XMLView_Moniker_Enum(IMoniker *iface,
719         BOOL fForward, IEnumMoniker **ppenumMoniker)
720 {
721     Moniker *This = impl_from_IMoniker(iface);
722     FIXME("(%p)->(%x %p)\n", This, fForward, ppenumMoniker);
723     return E_NOTIMPL;
724 }
725 
726 static HRESULT WINAPI XMLView_Moniker_IsEqual(IMoniker *iface,
727         IMoniker *pmkOtherMoniker)
728 {
729     Moniker *This = impl_from_IMoniker(iface);
730     FIXME("(%p)->(%p)\n", This, pmkOtherMoniker);
731     return E_NOTIMPL;
732 }
733 
734 static HRESULT WINAPI XMLView_Moniker_Hash(IMoniker *iface, DWORD *pdwHash)
735 {
736     Moniker *This = impl_from_IMoniker(iface);
737     FIXME("(%p)->(%p)\n", This, pdwHash);
738     return E_NOTIMPL;
739 }
740 
741 static HRESULT WINAPI XMLView_Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc,
742         IMoniker *pmkToLeft, IMoniker *pmkNewlyRunning)
743 {
744     Moniker *This = impl_from_IMoniker(iface);
745     FIXME("(%p)->(%p %p %p)\n", This, pbc, pmkToLeft, pmkNewlyRunning);
746     return E_NOTIMPL;
747 }
748 
749 static HRESULT WINAPI XMLView_Moniker_GetTimeOfLastChange(IMoniker *iface,
750         IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pFileTime)
751 {
752     Moniker *This = impl_from_IMoniker(iface);
753     FIXME("(%p)->(%p %p %p)\n", This, pbc, pmkToLeft, pFileTime);
754     return E_NOTIMPL;
755 }
756 
757 static HRESULT WINAPI XMLView_Moniker_Inverse(IMoniker *iface, IMoniker **ppmk)
758 {
759     Moniker *This = impl_from_IMoniker(iface);
760     FIXME("(%p)->(%p)\n", This, ppmk);
761     return E_NOTIMPL;
762 }
763 
764 static HRESULT WINAPI XMLView_Moniker_CommonPrefixWith(IMoniker *iface,
765         IMoniker *pmkOther, IMoniker **ppmkPrefix)
766 {
767     Moniker *This = impl_from_IMoniker(iface);
768     FIXME("(%p)->(%p %p)\n", This, pmkOther, ppmkPrefix);
769     return E_NOTIMPL;
770 }
771 
772 static HRESULT WINAPI XMLView_Moniker_RelativePathTo(IMoniker *iface,
773         IMoniker *pmkOther, IMoniker **ppmkRelPath)
774 {
775     Moniker *This = impl_from_IMoniker(iface);
776     FIXME("(%p)->(%p %p)\n", This, pmkOther, ppmkRelPath);
777     return E_NOTIMPL;
778 }
779 
780 static HRESULT WINAPI XMLView_Moniker_GetDisplayName(IMoniker *iface,
781         IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
782 {
783     Moniker *This = impl_from_IMoniker(iface);
784     TRACE("(%p)->(%p %p %p)\n", This, pbc, pmkToLeft, ppszDisplayName);
785     return IMoniker_GetDisplayName(This->mon, pbc, pmkToLeft, ppszDisplayName);
786 }
787 
788 static HRESULT WINAPI XMLView_Moniker_ParseDisplayName(IMoniker *iface,
789         IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR pszDisplayName,
790         ULONG *pchEaten, IMoniker **ppmkOut)
791 {
792     Moniker *This = impl_from_IMoniker(iface);
793     FIXME("(%p)->(%p %p %s %p %p)\n", This, pbc, pmkToLeft,
794             debugstr_w(pszDisplayName), pchEaten, ppmkOut);
795     return E_NOTIMPL;
796 }
797 
798 static HRESULT WINAPI XMLView_Moniker_IsSystemMoniker(
799         IMoniker *iface, DWORD *pdwMksys)
800 {
801     Moniker *This = impl_from_IMoniker(iface);
802     FIXME("(%p)->(%p)\n", This, pdwMksys);
803     return E_NOTIMPL;
804 }
805 
806 static IMonikerVtbl XMLView_MonikerVtbl = {
807     XMLView_Moniker_QueryInterface,
808     XMLView_Moniker_AddRef,
809     XMLView_Moniker_Release,
810     XMLView_Moniker_GetClassID,
811     XMLView_Moniker_IsDirty,
812     XMLView_Moniker_Load,
813     XMLView_Moniker_Save,
814     XMLView_Moniker_GetSizeMax,
815     XMLView_Moniker_BindToObject,
816     XMLView_Moniker_BindToStorage,
817     XMLView_Moniker_Reduce,
818     XMLView_Moniker_ComposeWith,
819     XMLView_Moniker_Enum,
820     XMLView_Moniker_IsEqual,
821     XMLView_Moniker_Hash,
822     XMLView_Moniker_IsRunning,
823     XMLView_Moniker_GetTimeOfLastChange,
824     XMLView_Moniker_Inverse,
825     XMLView_Moniker_CommonPrefixWith,
826     XMLView_Moniker_RelativePathTo,
827     XMLView_Moniker_GetDisplayName,
828     XMLView_Moniker_ParseDisplayName,
829     XMLView_Moniker_IsSystemMoniker
830 };
831 
832 static inline HRESULT XMLView_Moniker_Create(IMoniker *mon,
833         IStream *stream, IMoniker **ret)
834 {
835     Moniker *wrap;
836 
837     wrap = heap_alloc_zero(sizeof(Moniker));
838     if(!wrap)
839         return E_OUTOFMEMORY;
840 
841     wrap->IMoniker_iface.lpVtbl = &XMLView_MonikerVtbl;
842     wrap->ref = 1;
843 
844     wrap->mon = mon;
845     IMoniker_AddRef(mon);
846     wrap->stream = stream;
847     IStream_AddRef(stream);
848 
849     *ret = &wrap->IMoniker_iface;
850     return S_OK;
851 }
852 
853 static inline XMLView* impl_from_IPersistMoniker(IPersistMoniker *iface)
854 {
855     return CONTAINING_RECORD(iface, XMLView, IPersistMoniker_iface);
856 }
857 
858 static HRESULT WINAPI XMLView_PersistMoniker_QueryInterface(
859         IPersistMoniker *iface, REFIID riid, void **ppvObject)
860 {
861     XMLView *This = impl_from_IPersistMoniker(iface);
862 
863     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
864 
865     if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IPersistMoniker))
866         *ppvObject = &This->IPersistMoniker_iface;
867     else if(IsEqualGUID(riid, &IID_IPersistHistory) ||
868             IsEqualGUID(riid, &IID_IPersist))
869         *ppvObject = &This->IPersistHistory_iface;
870     else if(IsEqualGUID(riid, &IID_IOleCommandTarget))
871         *ppvObject = &This->IOleCommandTarget_iface;
872     else if(IsEqualGUID(riid, &IID_IOleObject))
873         *ppvObject = &This->IOleObject_iface;
874     else
875         return IUnknown_QueryInterface(This->html_doc, riid, ppvObject);
876 
877     IPersistMoniker_AddRef(&This->IPersistMoniker_iface);
878     return S_OK;
879 }
880 
881 static ULONG WINAPI XMLView_PersistMoniker_AddRef(IPersistMoniker *iface)
882 {
883     XMLView *This = impl_from_IPersistMoniker(iface);
884     LONG ref = InterlockedIncrement(&This->ref);
885 
886     TRACE("(%p)->(%d)\n", This, ref);
887 
888     return ref;
889 }
890 
891 static ULONG WINAPI XMLView_PersistMoniker_Release(IPersistMoniker *iface)
892 {
893     XMLView *This = impl_from_IPersistMoniker(iface);
894     ULONG ref = InterlockedDecrement(&This->ref);
895 
896     TRACE("(%p)->(%d)\n", This, ref);
897 
898     if(!ref) {
899         if(This->mon)
900             IMoniker_Release(This->mon);
901         IUnknown_Release(This->html_doc);
902         heap_free(This);
903     }
904     return ref;
905 }
906 
907 static HRESULT WINAPI XMLView_PersistMoniker_GetClassID(
908         IPersistMoniker *iface, CLSID *pClassID)
909 {
910     XMLView *This = impl_from_IPersistMoniker(iface);
911     FIXME("(%p)->(%p)\n", This, pClassID);
912     return E_NOTIMPL;
913 }
914 
915 static HRESULT WINAPI XMLView_PersistMoniker_IsDirty(IPersistMoniker *iface)
916 {
917     XMLView *This = impl_from_IPersistMoniker(iface);
918     FIXME("(%p)\n", This);
919     return E_NOTIMPL;
920 }
921 
922 static HRESULT WINAPI XMLView_PersistMoniker_Load(IPersistMoniker *iface,
923         BOOL fFullyAvailable, IMoniker *pimkName, LPBC pibc, DWORD grfMode)
924 {
925     static const WCHAR XSLParametersW[] = {'X','S','L','P','a','r','a','m','e','t','e','r','s',0};
926     static const WCHAR XMLBufferStreamW[] = {'X','M','L','B','u','f','f','e','r','S','t','r','e','a','m',0};
927     static const WCHAR DWNBINDINFOW[] = {'_','_','D','W','N','B','I','N','D','I','N','F','O',0};
928     static const WCHAR HTMLLOADOPTIONSW[] = {'_','_','H','T','M','L','L','O','A','D','O','P','T','I','O','N','S',0};
929     static const WCHAR BSCBHolderW[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
930 
931     XMLView *This = impl_from_IPersistMoniker(iface);
932     IPersistMoniker *html_persist_mon;
933     IBindStatusCallback *bsc, *bsc_html;
934     IBindCtx *bindctx;
935     IStream *stream;
936     IMoniker *mon;
937     IUnknown *unk;
938     HRESULT hres;
939 
940     TRACE("(%p)->(%x %p %p %x)\n", This, fFullyAvailable, pimkName, pibc, grfMode);
941 
942     hres = IBindCtx_GetObjectParam(pibc, (LPOLESTR)XSLParametersW, &unk);
943     if(SUCCEEDED(hres)) {
944         FIXME("ignoring XSLParameters\n");
945         IUnknown_Release(unk);
946     }
947     hres = IBindCtx_GetObjectParam(pibc, (LPOLESTR)XMLBufferStreamW, &unk);
948     if(SUCCEEDED(hres)) {
949         FIXME("ignoring XMLBufferStream\n");
950         IUnknown_Release(unk);
951     }
952 
953     hres = CreateBindCtx(0, &bindctx);
954     if(FAILED(hres))
955         return hres;
956 
957     hres = IBindCtx_GetObjectParam(pibc, (LPOLESTR)DWNBINDINFOW, &unk);
958     if(SUCCEEDED(hres)) {
959         IBindCtx_RegisterObjectParam(bindctx, (LPOLESTR)DWNBINDINFOW, unk);
960         IUnknown_Release(unk);
961     }
962     hres = IBindCtx_GetObjectParam(pibc, (LPOLESTR)HTMLLOADOPTIONSW, &unk);
963     if(SUCCEEDED(hres)) {
964         IBindCtx_RegisterObjectParam(bindctx, (LPOLESTR)HTMLLOADOPTIONSW, unk);
965         IUnknown_Release(unk);
966     }
967     hres = IBindCtx_GetObjectParam(pibc, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM, &unk);
968     if(SUCCEEDED(hres)) {
969         IBindCtx_RegisterObjectParam(bindctx, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM, unk);
970         IUnknown_Release(unk);
971     }
972 
973     hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
974     if(FAILED(hres)) {
975         IBindCtx_Release(bindctx);
976         return hres;
977     }
978 
979     if(This->mon)
980         IMoniker_Release(This->mon);
981     This->mon = pimkName;
982     IMoniker_AddRef(This->mon);
983 
984     hres = XMLView_Moniker_Create(This->mon, stream, &mon);
985     if(FAILED(hres)) {
986         IStream_Release(stream);
987         IBindCtx_Release(bindctx);
988         return hres;
989     }
990 
991     hres = IUnknown_QueryInterface(This->html_doc,
992             &IID_IPersistMoniker, (void**)&html_persist_mon);
993     if(FAILED(hres)) {
994         IMoniker_Release(mon);
995         IStream_Release(stream);
996         IBindCtx_Release(bindctx);
997         return hres;
998     }
999 
1000     hres = IPersistMoniker_Load(html_persist_mon, FALSE, mon, bindctx, 0);
1001     IPersistMoniker_Release(html_persist_mon);
1002     IMoniker_Release(mon);
1003     if(FAILED(hres)) {
1004         IStream_Release(stream);
1005         IBindCtx_Release(bindctx);
1006         return hres;
1007     }
1008 
1009     hres = IBindCtx_GetObjectParam(bindctx, (LPOLESTR)BSCBHolderW, &unk);
1010     IBindCtx_Release(bindctx);
1011     if(FAILED(hres)) {
1012         IStream_Release(stream);
1013         return hres;
1014     }
1015     hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc_html);
1016     IUnknown_Release(unk);
1017     if(FAILED(hres)) {
1018         IStream_Release(stream);
1019         return hres;
1020     }
1021 
1022     hres = XMLView_BindStatusCallback_Create(bsc_html, This->mon, stream, &bsc);
1023     IStream_Release(stream);
1024     if(FAILED(hres)) {
1025         IBindStatusCallback_OnStopBinding(bsc_html, hres, NULL);
1026         IBindStatusCallback_Release(bsc_html);
1027         return hres;
1028     }
1029 
1030     hres = RegisterBindStatusCallback(pibc, bsc, NULL, 0);
1031     IBindStatusCallback_Release(bsc);
1032     if(FAILED(hres)) {
1033         IBindStatusCallback_OnStopBinding(bsc_html, hres, NULL);
1034         IBindStatusCallback_Release(bsc_html);
1035         return hres;
1036     }
1037 
1038     hres = IMoniker_BindToStorage(pimkName, pibc, NULL,
1039             &IID_IStream, (void**)&stream);
1040     if(FAILED(hres)) {
1041         IBindStatusCallback_OnStopBinding(bsc_html, hres, NULL);
1042         IBindStatusCallback_Release(bsc_html);
1043         return hres;
1044     }
1045 
1046     if(stream)
1047         IStream_Release(stream);
1048     IBindStatusCallback_Release(bsc_html);
1049     return S_OK;
1050 }
1051 
1052 static HRESULT WINAPI XMLView_PersistMoniker_Save(IPersistMoniker *iface,
1053         IMoniker *pimkName, LPBC pbc, BOOL fRemember)
1054 {
1055     XMLView *This = impl_from_IPersistMoniker(iface);
1056     FIXME("(%p)->(%p %p %x)\n", This, pimkName, pbc, fRemember);
1057     return E_NOTIMPL;
1058 }
1059 
1060 static HRESULT WINAPI XMLView_PersistMoniker_SaveCompleted(
1061         IPersistMoniker *iface, IMoniker *pimkName, LPBC pibc)
1062 {
1063     XMLView *This = impl_from_IPersistMoniker(iface);
1064     FIXME("(%p)->(%p %p)\n", This, pimkName, pibc);
1065     return E_NOTIMPL;
1066 }
1067 
1068 static HRESULT WINAPI XMLView_PersistMoniker_GetCurMoniker(
1069         IPersistMoniker *iface, IMoniker **ppimkName)
1070 {
1071     XMLView *This = impl_from_IPersistMoniker(iface);
1072     FIXME("(%p)->(%p)\n", This, ppimkName);
1073     return E_NOTIMPL;
1074 }
1075 
1076 static IPersistMonikerVtbl XMLView_PersistMonikerVtbl = {
1077     XMLView_PersistMoniker_QueryInterface,
1078     XMLView_PersistMoniker_AddRef,
1079     XMLView_PersistMoniker_Release,
1080     XMLView_PersistMoniker_GetClassID,
1081     XMLView_PersistMoniker_IsDirty,
1082     XMLView_PersistMoniker_Load,
1083     XMLView_PersistMoniker_Save,
1084     XMLView_PersistMoniker_SaveCompleted,
1085     XMLView_PersistMoniker_GetCurMoniker
1086 };
1087 
1088 static inline XMLView* impl_from_IPersistHistory(IPersistHistory *iface)
1089 {
1090     return CONTAINING_RECORD(iface, XMLView, IPersistHistory_iface);
1091 }
1092 
1093 static HRESULT WINAPI XMLView_PersistHistory_QueryInterface(
1094         IPersistHistory *iface, REFIID riid, void **ppvObject)
1095 {
1096     XMLView *This = impl_from_IPersistHistory(iface);
1097     return IPersistMoniker_QueryInterface(&This->IPersistMoniker_iface, riid, ppvObject);
1098 }
1099 
1100 static ULONG WINAPI XMLView_PersistHistory_AddRef(IPersistHistory *iface)
1101 {
1102     XMLView *This = impl_from_IPersistHistory(iface);
1103     return IPersistMoniker_AddRef(&This->IPersistMoniker_iface);
1104 }
1105 
1106 static ULONG WINAPI XMLView_PersistHistory_Release(IPersistHistory *iface)
1107 {
1108     XMLView *This = impl_from_IPersistHistory(iface);
1109     return IPersistMoniker_Release(&This->IPersistMoniker_iface);
1110 }
1111 
1112 static HRESULT WINAPI XMLView_PersistHistory_GetClassID(
1113         IPersistHistory *iface, CLSID *pClassID)
1114 {
1115     XMLView *This = impl_from_IPersistHistory(iface);
1116     FIXME("(%p)->(%p)\n", This, pClassID);
1117     return E_NOTIMPL;
1118 }
1119 
1120 static HRESULT WINAPI XMLView_PersistHistory_LoadHistory(
1121         IPersistHistory *iface, IStream *pStream, IBindCtx *pbc)
1122 {
1123     XMLView *This = impl_from_IPersistHistory(iface);
1124     FIXME("(%p)->(%p %p)\n", This, pStream, pbc);
1125     return E_NOTIMPL;
1126 }
1127 
1128 static HRESULT WINAPI XMLView_PersistHistory_SaveHistory(
1129         IPersistHistory *iface, IStream *pStream)
1130 {
1131     XMLView *This = impl_from_IPersistHistory(iface);
1132     FIXME("(%p)->(%p)\n", This, pStream);
1133     return E_NOTIMPL;
1134 }
1135 
1136 static HRESULT WINAPI XMLView_PersistHistory_SetPositionCookie(
1137         IPersistHistory *iface, DWORD dwPositioncookie)
1138 {
1139     XMLView *This = impl_from_IPersistHistory(iface);
1140     FIXME("(%p)->(%d)\n", This, dwPositioncookie);
1141     return E_NOTIMPL;
1142 }
1143 
1144 static HRESULT WINAPI XMLView_PersistHistory_GetPositionCookie(
1145         IPersistHistory *iface, DWORD *pdwPositioncookie)
1146 {
1147     XMLView *This = impl_from_IPersistHistory(iface);
1148     FIXME("(%p)->(%p)\n", This, pdwPositioncookie);
1149     return E_NOTIMPL;
1150 }
1151 
1152 static IPersistHistoryVtbl XMLView_PersistHistoryVtbl = {
1153     XMLView_PersistHistory_QueryInterface,
1154     XMLView_PersistHistory_AddRef,
1155     XMLView_PersistHistory_Release,
1156     XMLView_PersistHistory_GetClassID,
1157     XMLView_PersistHistory_LoadHistory,
1158     XMLView_PersistHistory_SaveHistory,
1159     XMLView_PersistHistory_SetPositionCookie,
1160     XMLView_PersistHistory_GetPositionCookie
1161 };
1162 
1163 static inline XMLView* impl_from_IOleCommandTarget(IOleCommandTarget *iface)
1164 {
1165     return CONTAINING_RECORD(iface, XMLView, IOleCommandTarget_iface);
1166 }
1167 
1168 static HRESULT WINAPI XMLView_OleCommandTarget_QueryInterface(
1169         IOleCommandTarget *iface, REFIID riid, void **ppvObject)
1170 {
1171     XMLView *This = impl_from_IOleCommandTarget(iface);
1172     return IPersistMoniker_QueryInterface(&This->IPersistMoniker_iface, riid, ppvObject);
1173 }
1174 
1175 static ULONG WINAPI XMLView_OleCommandTarget_AddRef(IOleCommandTarget *iface)
1176 {
1177     XMLView *This = impl_from_IOleCommandTarget(iface);
1178     return IPersistMoniker_AddRef(&This->IPersistMoniker_iface);
1179 }
1180 
1181 static ULONG WINAPI XMLView_OleCommandTarget_Release(IOleCommandTarget *iface)
1182 {
1183     XMLView *This = impl_from_IOleCommandTarget(iface);
1184     return IPersistMoniker_Release(&This->IPersistMoniker_iface);
1185 }
1186 
1187 static HRESULT WINAPI XMLView_OleCommandTarget_QueryStatus(IOleCommandTarget *iface,
1188         const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
1189 {
1190     XMLView *This = impl_from_IOleCommandTarget(iface);
1191     FIXME("(%p)->(%p %x %p %p)\n", This, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1192     return E_NOTIMPL;
1193 }
1194 
1195 static HRESULT WINAPI XMLView_OleCommandTarget_Exec(IOleCommandTarget *iface,
1196         const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
1197         VARIANT *pvaIn, VARIANT *pvaOut)
1198 {
1199     XMLView *This = impl_from_IOleCommandTarget(iface);
1200     FIXME("(%p)->(%p %d %x %p %p)\n", This, pguidCmdGroup,
1201             nCmdID, nCmdexecopt, pvaIn, pvaOut);
1202     return E_NOTIMPL;
1203 }
1204 
1205 static IOleCommandTargetVtbl XMLView_OleCommandTargetVtbl = {
1206     XMLView_OleCommandTarget_QueryInterface,
1207     XMLView_OleCommandTarget_AddRef,
1208     XMLView_OleCommandTarget_Release,
1209     XMLView_OleCommandTarget_QueryStatus,
1210     XMLView_OleCommandTarget_Exec
1211 };
1212 
1213 static inline XMLView* impl_from_IOleObject(IOleObject *iface)
1214 {
1215     return CONTAINING_RECORD(iface, XMLView, IOleObject_iface);
1216 }
1217 
1218 static HRESULT WINAPI XMLView_OleObject_QueryInterface(
1219         IOleObject *iface, REFIID riid, void **ppvObject)
1220 {
1221     XMLView *This = impl_from_IOleObject(iface);
1222     return IPersistMoniker_QueryInterface(&This->IPersistMoniker_iface, riid, ppvObject);
1223 }
1224 
1225 static ULONG WINAPI XMLView_OleObject_AddRef(IOleObject *iface)
1226 {
1227     XMLView *This = impl_from_IOleObject(iface);
1228     return IPersistMoniker_AddRef(&This->IPersistMoniker_iface);
1229 }
1230 
1231 static ULONG WINAPI XMLView_OleObject_Release(IOleObject *iface)
1232 {
1233     XMLView *This = impl_from_IOleObject(iface);
1234     return IPersistMoniker_Release(&This->IPersistMoniker_iface);
1235 }
1236 
1237 static HRESULT WINAPI XMLView_OleObject_SetClientSite(
1238         IOleObject *iface, IOleClientSite *pClientSite)
1239 {
1240     XMLView *This = impl_from_IOleObject(iface);
1241     FIXME("(%p)->(%p)\n", This, pClientSite);
1242     return E_NOTIMPL;
1243 }
1244 
1245 static HRESULT WINAPI XMLView_OleObject_GetClientSite(
1246         IOleObject *iface, IOleClientSite **ppClientSite)
1247 {
1248     XMLView *This = impl_from_IOleObject(iface);
1249     FIXME("(%p)->(%p)\n", This, ppClientSite);
1250     return E_NOTIMPL;
1251 }
1252 
1253 static HRESULT WINAPI XMLView_OleObject_SetHostNames(IOleObject *iface,
1254         LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
1255 {
1256     XMLView *This = impl_from_IOleObject(iface);
1257     FIXME("(%p)->(%s %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj));
1258     return E_NOTIMPL;
1259 }
1260 
1261 static HRESULT WINAPI XMLView_OleObject_Close(IOleObject *iface, DWORD dwSaveOption)
1262 {
1263     XMLView *This = impl_from_IOleObject(iface);
1264     FIXME("(%p)->(%x)\n", This, dwSaveOption);
1265     return E_NOTIMPL;
1266 }
1267 
1268 static HRESULT WINAPI XMLView_OleObject_SetMoniker(IOleObject *iface,
1269         DWORD dwWhichMoniker, IMoniker *pmk)
1270 {
1271     XMLView *This = impl_from_IOleObject(iface);
1272     FIXME("(%p)->(%x %p)\n", This, dwWhichMoniker, pmk);
1273     return E_NOTIMPL;
1274 }
1275 
1276 static HRESULT WINAPI XMLView_OleObject_GetMoniker(IOleObject *iface,
1277         DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
1278 {
1279     XMLView *This = impl_from_IOleObject(iface);
1280     FIXME("(%p)->(%x %x %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
1281     return E_NOTIMPL;
1282 }
1283 
1284 static HRESULT WINAPI XMLView_OleObject_InitFromData(IOleObject *iface,
1285         IDataObject *pDataObject, BOOL fCreation, DWORD dwReserved)
1286 {
1287     XMLView *This = impl_from_IOleObject(iface);
1288     FIXME("(%p)->(%p %x %x)\n", This, pDataObject, fCreation, dwReserved);
1289     return E_NOTIMPL;
1290 }
1291 
1292 static HRESULT WINAPI XMLView_OleObject_GetClipboardData(IOleObject *iface,
1293         DWORD dwReserved, IDataObject **ppDataObject)
1294 {
1295     XMLView *This = impl_from_IOleObject(iface);
1296     FIXME("(%p)->(%x %p)\n", This, dwReserved, ppDataObject);
1297     return E_NOTIMPL;
1298 }
1299 
1300 static HRESULT WINAPI XMLView_OleObject_DoVerb(IOleObject *iface,
1301         LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite,
1302         LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
1303 {
1304     XMLView *This = impl_from_IOleObject(iface);
1305     FIXME("(%p)->(%d %p %p %d %p %p)\n", This, iVerb, lpmsg,
1306             pActiveSite, lindex, hwndParent, lprcPosRect);
1307     return E_NOTIMPL;
1308 }
1309 
1310 static HRESULT WINAPI XMLView_OleObject_EnumVerbs(
1311         IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb)
1312 {
1313     XMLView *This = impl_from_IOleObject(iface);
1314     FIXME("(%p)->{%p)\n", This, ppEnumOleVerb);
1315     return E_NOTIMPL;
1316 }
1317 
1318 static HRESULT WINAPI XMLView_OleObject_Update(IOleObject *iface)
1319 {
1320     XMLView *This = impl_from_IOleObject(iface);
1321     FIXME("(%p)\n", This);
1322     return E_NOTIMPL;
1323 }
1324 
1325 static HRESULT WINAPI XMLView_OleObject_IsUpToDate(IOleObject *iface)
1326 {
1327     XMLView *This = impl_from_IOleObject(iface);
1328     FIXME("(%p)\n", This);
1329     return E_NOTIMPL;
1330 }
1331 
1332 static HRESULT WINAPI XMLView_OleObject_GetUserClassID(IOleObject *iface, CLSID *pClsid)
1333 {
1334     XMLView *This = impl_from_IOleObject(iface);
1335     FIXME("(%p)->(%p)\n", This, pClsid);
1336     return E_NOTIMPL;
1337 }
1338 
1339 static HRESULT WINAPI XMLView_OleObject_GetUserType(IOleObject *iface,
1340         DWORD dwFormOfType, LPOLESTR *pszUserType)
1341 {
1342     XMLView *This = impl_from_IOleObject(iface);
1343     FIXME("(%p)->(%x %p)\n", This, dwFormOfType, pszUserType);
1344     return E_NOTIMPL;
1345 }
1346 
1347 static HRESULT WINAPI XMLView_OleObject_SetExtent(IOleObject *iface,
1348         DWORD dwDrawAspect, SIZEL *psizel)
1349 {
1350     XMLView *This = impl_from_IOleObject(iface);
1351     FIXME("(%p)->(%x %p)\n", This, dwDrawAspect, psizel);
1352     return E_NOTIMPL;
1353 }
1354 
1355 static HRESULT WINAPI XMLView_OleObject_GetExtent(IOleObject *iface,
1356         DWORD dwDrawAspect, SIZEL *psizel)
1357 {
1358     XMLView *This = impl_from_IOleObject(iface);
1359     FIXME("(%p)->(%x %p)\n", This, dwDrawAspect, psizel);
1360     return E_NOTIMPL;
1361 }
1362 
1363 static HRESULT WINAPI XMLView_OleObject_Advise(IOleObject *iface,
1364         IAdviseSink *pAdvSink, DWORD *pdwConnection)
1365 {
1366     XMLView *This = impl_from_IOleObject(iface);
1367     FIXME("(%p)->(%p %p)\n", This, pAdvSink, pdwConnection);
1368     return E_NOTIMPL;
1369 }
1370 
1371 static HRESULT WINAPI XMLView_OleObject_Unadvise(
1372         IOleObject *iface, DWORD dwConnection)
1373 {
1374     XMLView *This = impl_from_IOleObject(iface);
1375     FIXME("(%p)->(%d)\n", This, dwConnection);
1376     return E_NOTIMPL;
1377 }
1378 
1379 static HRESULT WINAPI XMLView_OleObject_EnumAdvise(
1380         IOleObject *iface, IEnumSTATDATA **ppenumAdvise)
1381 {
1382     XMLView *This = impl_from_IOleObject(iface);
1383     FIXME("(%p)->(%p)\n", This, ppenumAdvise);
1384     return E_NOTIMPL;
1385 }
1386 
1387 static HRESULT WINAPI XMLView_OleObject_GetMiscStatus(
1388         IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus)
1389 {
1390     XMLView *This = impl_from_IOleObject(iface);
1391     FIXME("(%p)->(%d %p)\n", This, dwAspect, pdwStatus);
1392     return E_NOTIMPL;
1393 }
1394 
1395 static HRESULT WINAPI XMLView_OleObject_SetColorScheme(
1396         IOleObject *iface, LOGPALETTE *pLogpal)
1397 {
1398     XMLView *This = impl_from_IOleObject(iface);
1399     FIXME("(%p)->(%p)\n", This, pLogpal);
1400     return E_NOTIMPL;
1401 }
1402 
1403 static IOleObjectVtbl XMLView_OleObjectVtbl = {
1404     XMLView_OleObject_QueryInterface,
1405     XMLView_OleObject_AddRef,
1406     XMLView_OleObject_Release,
1407     XMLView_OleObject_SetClientSite,
1408     XMLView_OleObject_GetClientSite,
1409     XMLView_OleObject_SetHostNames,
1410     XMLView_OleObject_Close,
1411     XMLView_OleObject_SetMoniker,
1412     XMLView_OleObject_GetMoniker,
1413     XMLView_OleObject_InitFromData,
1414     XMLView_OleObject_GetClipboardData,
1415     XMLView_OleObject_DoVerb,
1416     XMLView_OleObject_EnumVerbs,
1417     XMLView_OleObject_Update,
1418     XMLView_OleObject_IsUpToDate,
1419     XMLView_OleObject_GetUserClassID,
1420     XMLView_OleObject_GetUserType,
1421     XMLView_OleObject_SetExtent,
1422     XMLView_OleObject_GetExtent,
1423     XMLView_OleObject_Advise,
1424     XMLView_OleObject_Unadvise,
1425     XMLView_OleObject_EnumAdvise,
1426     XMLView_OleObject_GetMiscStatus,
1427     XMLView_OleObject_SetColorScheme
1428 };
1429 
1430 HRESULT XMLView_create(void **ppObj)
1431 {
1432     XMLView *This;
1433     HRESULT hres;
1434 
1435     TRACE("(%p)\n", ppObj);
1436 
1437     This = heap_alloc_zero(sizeof(*This));
1438     if(!This)
1439         return E_OUTOFMEMORY;
1440 
1441     This->IPersistMoniker_iface.lpVtbl = &XMLView_PersistMonikerVtbl;
1442     This->IPersistHistory_iface.lpVtbl = &XMLView_PersistHistoryVtbl;
1443     This->IOleCommandTarget_iface.lpVtbl = &XMLView_OleCommandTargetVtbl;
1444     This->IOleObject_iface.lpVtbl = &XMLView_OleObjectVtbl;
1445     This->ref = 1;
1446 
1447     hres = CoCreateInstance(&CLSID_HTMLDocument, (IUnknown*)&This->IPersistMoniker_iface,
1448             CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&This->html_doc);
1449     if(FAILED(hres)) {
1450         heap_free(This);
1451         return hres;
1452     }
1453 
1454     *ppObj = &This->IPersistMoniker_iface;
1455     return S_OK;
1456 }
1457 
1458 #else
1459 
1460 HRESULT XMLView_create(void **ppObj)
1461 {
1462     MESSAGE("This program tried to use a XMLView object, but\n"
1463             "libxml2 support was not present at compile time.\n");
1464     return E_NOTIMPL;
1465 }
1466 
1467 #endif /* HAVE_LIBXML2 */
1468