comctl32: A couple fixes for tab icon offsets.
[wine] / dlls / mshtml / oleobj.c
1 /*
2  * Copyright 2005 Jacek Caban
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "shlguid.h"
31 #include "mshtmdid.h"
32 #include "idispids.h"
33
34 #include "wine/debug.h"
35
36 #include "mshtml_private.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
39
40 /**********************************************************
41  * IOleObject implementation
42  */
43
44 #define OLEOBJ_THIS(iface) DEFINE_THIS(HTMLDocument, OleObject, iface)
45
46 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppvObject)
47 {
48     HTMLDocument *This = OLEOBJ_THIS(iface);
49     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
50 }
51
52 static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
53 {
54     HTMLDocument *This = OLEOBJ_THIS(iface);
55     return IHTMLDocument2_AddRef(HTMLDOC(This));
56 }
57
58 static ULONG WINAPI OleObject_Release(IOleObject *iface)
59 {
60     HTMLDocument *This = OLEOBJ_THIS(iface);
61     return IHTMLDocument2_Release(HTMLDOC(This));
62 }
63
64 static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, IOleClientSite *pClientSite)
65 {
66     HTMLDocument *This = OLEOBJ_THIS(iface);
67     IDocHostUIHandler *pDocHostUIHandler = NULL;
68     IOleCommandTarget *cmdtrg = NULL;
69     HRESULT hres;
70
71     TRACE("(%p)->(%p)\n", This, pClientSite);
72
73     if(pClientSite == This->client)
74         return S_OK;
75
76     if(This->client) {
77         IOleClientSite_Release(This->client);
78         This->client = NULL;
79     }
80
81     if(This->hostui) {
82         IDocHostUIHandler_Release(This->hostui);
83         This->hostui = NULL;
84     }
85
86     if(!pClientSite)
87         return S_OK;
88
89     hres = IOleObject_QueryInterface(pClientSite, &IID_IDocHostUIHandler, (void**)&pDocHostUIHandler);
90     if(SUCCEEDED(hres)) {
91         DOCHOSTUIINFO hostinfo;
92         LPOLESTR key_path = NULL, override_key_path = NULL;
93         IDocHostUIHandler2 *pDocHostUIHandler2;
94
95         memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
96         hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
97         hres = IDocHostUIHandler_GetHostInfo(pDocHostUIHandler, &hostinfo);
98         if(SUCCEEDED(hres))
99             /* FIXME: use hostinfo */
100             TRACE("hostinfo = {%lu %08lx %08lx %s %s}\n",
101                     hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
102                     debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
103
104         if(!This->has_key_path) {
105             hres = IDocHostUIHandler_GetOptionKeyPath(pDocHostUIHandler, &key_path, 0);
106             if(hres == S_OK && key_path) {
107                 if(key_path[0]) {
108                     /* FIXME: use key_path */
109                     TRACE("key_path = %s\n", debugstr_w(key_path));
110                 }
111                 CoTaskMemFree(key_path);
112             }
113
114             hres = IDocHostUIHandler_QueryInterface(pDocHostUIHandler, &IID_IDocHostUIHandler2,
115                     (void**)&pDocHostUIHandler2);
116             if(SUCCEEDED(hres)) {
117                 hres = IDocHostUIHandler2_GetOverrideKeyPath(pDocHostUIHandler2, &override_key_path, 0);
118                 if(hres == S_OK && override_key_path && override_key_path[0]) {
119                     if(override_key_path[0]) {
120                         /*FIXME: use override_key_path */
121                         TRACE("override_key_path = %s\n", debugstr_w(override_key_path));
122                     }
123                     CoTaskMemFree(override_key_path);
124                 }
125                 IDocHostUIHandler2_Release(pDocHostUIHandler2);
126             }
127
128             This->has_key_path = TRUE;
129         }
130     }
131
132     /* Native calls here GetWindow. What is it for?
133      * We don't have anything to do with it here (yet). */
134     if(pClientSite) {
135         IOleWindow *pOleWindow = NULL;
136         HWND hwnd;
137
138         hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleWindow, (void**)&pOleWindow);
139         if(SUCCEEDED(hres)) {
140             IOleWindow_GetWindow(pOleWindow, &hwnd);
141             IOleWindow_Release(pOleWindow);
142         }
143     }
144
145     hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleCommandTarget, (void**)&cmdtrg);
146     if(SUCCEEDED(hres)) {
147         VARIANT var;
148         OLECMD cmd = {OLECMDID_SETPROGRESSTEXT, 0};
149
150         IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &cmd, NULL);
151
152         V_VT(&var) = VT_I4;
153         V_I4(&var) = 0;
154         IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSMAX, 0, &var, NULL);
155         IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSPOS, 0, &var, NULL);
156
157         IOleCommandTarget_Release(cmdtrg);
158     }
159
160     IOleClientSite_AddRef(pClientSite);
161     This->client = pClientSite;
162     This->hostui = pDocHostUIHandler;
163
164     IOleControl_OnAmbientPropertyChange(CONTROL(This), DISPID_AMBIENT_USERMODE);
165     IOleControl_OnAmbientPropertyChange(CONTROL(This), DISPID_AMBIENT_OFFLINEIFNOTCONNECTED); 
166     IOleControl_OnAmbientPropertyChange(CONTROL(This), DISPID_AMBIENT_SILENT);
167     IOleControl_OnAmbientPropertyChange(CONTROL(This), DISPID_AMBIENT_USERAGENT);
168     IOleControl_OnAmbientPropertyChange(CONTROL(This), DISPID_AMBIENT_PALETTE);
169
170     return S_OK;
171 }
172
173 static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, IOleClientSite **ppClientSite)
174 {
175     HTMLDocument *This = OLEOBJ_THIS(iface);
176
177     TRACE("(%p)->(%p)\n", This, ppClientSite);
178
179     if(!ppClientSite)
180         return E_INVALIDARG;
181
182     if(This->client)
183         IOleClientSite_AddRef(This->client);
184     *ppClientSite = This->client;
185
186     return S_OK;
187 }
188
189 static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
190 {
191     HTMLDocument *This = OLEOBJ_THIS(iface);
192     FIXME("(%p)->(%s %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj));
193     return E_NOTIMPL;
194 }
195
196 static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption)
197 {
198     HTMLDocument *This = OLEOBJ_THIS(iface);
199
200     TRACE("(%p)->(%08lx)\n", This, dwSaveOption);
201
202     if(dwSaveOption == OLECLOSE_PROMPTSAVE)
203         FIXME("OLECLOSE_PROMPTSAVE not implemented\n");
204
205     if(This->in_place_active)
206         IOleInPlaceObjectWindowless_InPlaceDeactivate(INPLACEWIN(This));
207
208     HTMLDocument_LockContainer(This, FALSE);
209     
210     return S_OK;
211 }
212
213 static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker *pmk)
214 {
215     HTMLDocument *This = OLEOBJ_THIS(iface);
216     FIXME("(%p %ld %p)->()\n", This, dwWhichMoniker, pmk);
217     return E_NOTIMPL;
218 }
219
220 static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
221 {
222     HTMLDocument *This = OLEOBJ_THIS(iface);
223     FIXME("(%p)->(%ld %ld %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
224     return E_NOTIMPL;
225 }
226
227 static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, IDataObject *pDataObject, BOOL fCreation,
228                                         DWORD dwReserved)
229 {
230     HTMLDocument *This = OLEOBJ_THIS(iface);
231     FIXME("(%p)->(%p %x %ld)\n", This, pDataObject, fCreation, dwReserved);
232     return E_NOTIMPL;
233 }
234
235 static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved, IDataObject **ppDataObject)
236 {
237     HTMLDocument *This = OLEOBJ_THIS(iface);
238     FIXME("(%p)->(%ld %p)\n", This, dwReserved, ppDataObject);
239     return E_NOTIMPL;
240 }
241
242 static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite,
243                                         LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
244 {
245     HTMLDocument *This = OLEOBJ_THIS(iface);
246     IOleDocumentSite *pDocSite;
247     HRESULT hres;
248
249     TRACE("(%p)->(%ld %p %p %ld %p %p)\n", This, iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect);
250
251     if(iVerb != OLEIVERB_SHOW && iVerb != OLEIVERB_UIACTIVATE && iVerb != OLEIVERB_INPLACEACTIVATE) { 
252         FIXME("iVerb = %ld not supported\n", iVerb);
253         return E_NOTIMPL;
254     }
255
256     if(!pActiveSite)
257         pActiveSite = This->client;
258
259     hres = IOleClientSite_QueryInterface(pActiveSite, &IID_IOleDocumentSite, (void**)&pDocSite);
260     if(SUCCEEDED(hres)) {
261         HTMLDocument_LockContainer(This, TRUE);
262
263         /* FIXME: Create new IOleDocumentView. See CreateView for more info. */
264         hres = IOleDocumentSite_ActivateMe(pDocSite, DOCVIEW(This));
265         IOleDocumentSite_Release(pDocSite);
266     }else {
267         hres = IOleDocumentView_UIActivate(DOCVIEW(This), TRUE);
268         if(SUCCEEDED(hres)) {
269             if(lprcPosRect) {
270                 RECT rect; /* We need to pass rect as not const pointer */
271                 memcpy(&rect, lprcPosRect, sizeof(RECT));
272                 IOleDocumentView_SetRect(DOCVIEW(This), &rect);
273             }
274             IOleDocumentView_Show(DOCVIEW(This), TRUE);
275         }
276     }
277
278     return hres;
279 }
280
281 static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb)
282 {
283     HTMLDocument *This = OLEOBJ_THIS(iface);
284     FIXME("(%p)->(%p)\n", This, ppEnumOleVerb);
285     return E_NOTIMPL;
286 }
287
288 static HRESULT WINAPI OleObject_Update(IOleObject *iface)
289 {
290     HTMLDocument *This = OLEOBJ_THIS(iface);
291     FIXME("(%p)\n", This);
292     return E_NOTIMPL;
293 }
294
295 static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface)
296 {
297     HTMLDocument *This = OLEOBJ_THIS(iface);
298     FIXME("(%p)\n", This);
299     return E_NOTIMPL;
300 }
301
302 static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID *pClsid)
303 {
304     HTMLDocument *This = OLEOBJ_THIS(iface);
305
306     TRACE("(%p)->(%p)\n", This, pClsid);
307
308     if(!pClsid)
309         return E_INVALIDARG;
310
311     memcpy(pClsid, &CLSID_HTMLDocument, sizeof(GUID));
312     return S_OK;
313 }
314
315 static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType, LPOLESTR *pszUserType)
316 {
317     HTMLDocument *This = OLEOBJ_THIS(iface);
318     FIXME("(%p)->(%ld %p)\n", This, dwFormOfType, pszUserType);
319     return E_NOTIMPL;
320 }
321
322 static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
323 {
324     HTMLDocument *This = OLEOBJ_THIS(iface);
325     FIXME("(%p)->(%ld %p)\n", This, dwDrawAspect, psizel);
326     return E_NOTIMPL;
327 }
328
329 static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
330 {
331     HTMLDocument *This = OLEOBJ_THIS(iface);
332     FIXME("(%p)->(%ld %p)\n", This, dwDrawAspect, psizel);
333     return E_NOTIMPL;
334 }
335
336 static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink, DWORD *pdwConnection)
337 {
338     HTMLDocument *This = OLEOBJ_THIS(iface);
339     FIXME("(%p)->(%p %p)\n", This, pAdvSink, pdwConnection);
340     return E_NOTIMPL;
341 }
342
343 static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection)
344 {
345     HTMLDocument *This = OLEOBJ_THIS(iface);
346     FIXME("(%p)->(%ld)\n", This, dwConnection);
347     return E_NOTIMPL;
348 }
349
350 static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise)
351 {
352     HTMLDocument *This = OLEOBJ_THIS(iface);
353     FIXME("(%p)->(%p)\n", This, ppenumAdvise);
354     return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus)
358 {
359     HTMLDocument *This = OLEOBJ_THIS(iface);
360     FIXME("(%p)->(%ld %p)\n", This, dwAspect, pdwStatus);
361     return E_NOTIMPL;
362 }
363
364 static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE *pLogpal)
365 {
366     HTMLDocument *This = OLEOBJ_THIS(iface);
367     FIXME("(%p)->(%p)\n", This, pLogpal);
368     return E_NOTIMPL;
369 }
370
371 #undef OLEPBJ_THIS
372
373 static const IOleObjectVtbl OleObjectVtbl = {
374     OleObject_QueryInterface,
375     OleObject_AddRef,
376     OleObject_Release,
377     OleObject_SetClientSite,
378     OleObject_GetClientSite,
379     OleObject_SetHostNames,
380     OleObject_Close,
381     OleObject_SetMoniker,
382     OleObject_GetMoniker,
383     OleObject_InitFromData,
384     OleObject_GetClipboardData,
385     OleObject_DoVerb,
386     OleObject_EnumVerbs,
387     OleObject_Update,
388     OleObject_IsUpToDate,
389     OleObject_GetUserClassID,
390     OleObject_GetUserType,
391     OleObject_SetExtent,
392     OleObject_GetExtent,
393     OleObject_Advise,
394     OleObject_Unadvise,
395     OleObject_EnumAdvise,
396     OleObject_GetMiscStatus,
397     OleObject_SetColorScheme
398 };
399
400 /**********************************************************
401  * IOleDocument implementation
402  */
403
404 #define OLEDOC_THIS(iface) DEFINE_THIS(HTMLDocument, OleDocument, iface)
405
406 static HRESULT WINAPI OleDocument_QueryInterface(IOleDocument *iface, REFIID riid, void **ppvObject)
407 {
408     HTMLDocument *This = OLEDOC_THIS(iface);
409     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
410 }
411
412 static ULONG WINAPI OleDocument_AddRef(IOleDocument *iface)
413 {
414     HTMLDocument *This = OLEDOC_THIS(iface);
415     return IHTMLDocument2_AddRef(HTMLDOC(This));
416 }
417
418 static ULONG WINAPI OleDocument_Release(IOleDocument *iface)
419 {
420     HTMLDocument *This = OLEDOC_THIS(iface);
421     return IHTMLDocument2_Release(HTMLDOC(This));
422 }
423
424 static HRESULT WINAPI OleDocument_CreateView(IOleDocument *iface, IOleInPlaceSite *pIPSite, IStream *pstm,
425                                    DWORD dwReserved, IOleDocumentView **ppView)
426 {
427     HTMLDocument *This = OLEDOC_THIS(iface);
428     HRESULT hres;
429
430     TRACE("(%p)->(%p %p %ld %p)\n", This, pIPSite, pstm, dwReserved, ppView);
431
432     if(!ppView)
433         return E_INVALIDARG;
434
435     /* FIXME:
436      * Windows implementation creates new IOleDocumentView when function is called for the
437      * first time and returns E_FAIL when it is called for the second time, but it doesn't matter
438      * if the application uses returned interfaces, passed to ActivateMe or returned by
439      * QueryInterface, so there is no reason to create new interface. This needs more testing.
440      */
441
442     if(pIPSite) {
443         hres = IOleDocumentView_SetInPlaceSite(DOCVIEW(This), pIPSite);
444         if(FAILED(hres))
445             return hres;
446     }
447
448     if(pstm)
449         FIXME("pstm is not supported\n");
450
451     IOleDocumentView_AddRef(DOCVIEW(This));
452     *ppView = DOCVIEW(This);
453     return S_OK;
454 }
455
456 static HRESULT WINAPI OleDocument_GetDocMiscStatus(IOleDocument *iface, DWORD *pdwStatus)
457 {
458     HTMLDocument *This = OLEDOC_THIS(iface);
459     FIXME("(%p)->(%p)\n", This, pdwStatus);
460     return E_NOTIMPL;
461 }
462
463 static HRESULT WINAPI OleDocument_EnumViews(IOleDocument *iface, IEnumOleDocumentViews **ppEnum,
464                                    IOleDocumentView **ppView)
465 {
466     HTMLDocument *This = OLEDOC_THIS(iface);
467     FIXME("(%p)->(%p %p)\n", This, ppEnum, ppView);
468     return E_NOTIMPL;
469 }
470
471 #undef OLEDOC_THIS
472
473 static const IOleDocumentVtbl OleDocumentVtbl = {
474     OleDocument_QueryInterface,
475     OleDocument_AddRef,
476     OleDocument_Release,
477     OleDocument_CreateView,
478     OleDocument_GetDocMiscStatus,
479     OleDocument_EnumViews
480 };
481
482 /**********************************************************
483  * IOleCommandTarget implementation
484  */
485
486 #define CMDTARGET_THIS(iface) DEFINE_THIS(HTMLDocument, OleCommandTarget, iface)
487
488 static HRESULT exec_open(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
489 {
490     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
491     return E_NOTIMPL;
492 }
493
494 static HRESULT exec_new(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
495 {
496     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
497     return E_NOTIMPL;
498 }
499
500 static HRESULT exec_save(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
501 {
502     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
503     return E_NOTIMPL;
504 }
505
506 static HRESULT exec_save_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
507 {
508     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
509     return E_NOTIMPL;
510 }
511
512 static HRESULT exec_save_copy_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
513 {
514     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
515     return E_NOTIMPL;
516 }
517
518 static HRESULT exec_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
519 {
520     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
521     return E_NOTIMPL;
522 }
523
524 static HRESULT exec_print_preview(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
525 {
526     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
527     return E_NOTIMPL;
528 }
529
530 static HRESULT exec_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
531 {
532     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
533     return E_NOTIMPL;
534 }
535
536 static HRESULT exec_spell(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
537 {
538     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
539     return E_NOTIMPL;
540 }
541
542 static HRESULT exec_properties(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
543 {
544     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
545     return E_NOTIMPL;
546 }
547
548 static HRESULT exec_cut(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
549 {
550     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
551     return E_NOTIMPL;
552 }
553
554 static HRESULT exec_copy(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
555 {
556     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
557     return E_NOTIMPL;
558 }
559
560 static HRESULT exec_paste(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
561 {
562     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
563     return E_NOTIMPL;
564 }
565
566 static HRESULT exec_paste_special(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
567 {
568     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
569     return E_NOTIMPL;
570 }
571
572 static HRESULT exec_undo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
573 {
574     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
575     return E_NOTIMPL;
576 }
577
578 static HRESULT exec_rendo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
579 {
580     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
581     return E_NOTIMPL;
582 }
583
584 static HRESULT exec_select_all(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
585 {
586     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
587     return E_NOTIMPL;
588 }
589
590 static HRESULT exec_clear_selection(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
591 {
592     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
593     return E_NOTIMPL;
594 }
595
596 static HRESULT exec_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
597 {
598     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
599     return E_NOTIMPL;
600 }
601
602 static HRESULT exec_get_zoom_range(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
603 {
604     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
605     return E_NOTIMPL;
606 }
607
608 static HRESULT exec_refresh(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
609 {
610     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
611     return E_NOTIMPL;
612 }
613
614 static HRESULT exec_stop(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
615 {
616     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
617     return E_NOTIMPL;
618 }
619
620 static HRESULT exec_stop_download(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
621 {
622     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
623     return E_NOTIMPL;
624 }
625
626 static HRESULT exec_delete(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
627 {
628     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
629     return E_NOTIMPL;
630 }
631
632 static HRESULT exec_enable_interaction(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
633 {
634     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
635     return E_NOTIMPL;
636 }
637
638 static HRESULT exec_on_unload(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
639 {
640     TRACE("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
641
642     /* Tests show that we have nothing more to do here */
643
644     if(pvaOut) {
645         V_VT(pvaOut) = VT_BOOL;
646         V_BOOL(pvaOut) = VARIANT_TRUE;
647     }
648
649     return S_OK;
650 }
651
652 static HRESULT exec_show_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
653 {
654     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
655     return E_NOTIMPL;
656 }
657
658 static HRESULT exec_show_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
659 {
660     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
661     return E_NOTIMPL;
662 }
663
664 static HRESULT exec_close(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
665 {
666     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
667     return E_NOTIMPL;
668 }
669
670 static HRESULT exec_set_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
671 {
672     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
673     return E_NOTIMPL;
674 }
675
676 static HRESULT exec_get_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
677 {
678     FIXME("(%p)->(%ld %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
679     return E_NOTIMPL;
680 }
681
682 static const struct {
683     OLECMDF cmdf;
684     HRESULT (*func)(HTMLDocument*,DWORD,VARIANT*,VARIANT*);
685 } exec_table[OLECMDID_GETPRINTTEMPLATE+1] = {
686     {0},
687     { OLECMDF_SUPPORTED,                  exec_open                 }, /* OLECMDID_OPEN */
688     { OLECMDF_SUPPORTED,                  exec_new                  }, /* OLECMDID_NEW */
689     { OLECMDF_SUPPORTED,                  exec_save                 }, /* OLECMDID_SAVE */
690     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_save_as              }, /* OLECMDID_SAVEAS */
691     { OLECMDF_SUPPORTED,                  exec_save_copy_as         }, /* OLECMDID_SAVECOPYAS */
692     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_print                }, /* OLECMDID_PRINT */
693     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_print_preview        }, /* OLECMDID_PRINTPREVIEW */
694     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_page_setup           }, /* OLECMDID_PAGESETUP */
695     { OLECMDF_SUPPORTED,                  exec_spell                }, /* OLECMDID_SPELL */
696     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_properties           }, /* OLECMDID_PROPERTIES */
697     { OLECMDF_SUPPORTED,                  exec_cut                  }, /* OLECMDID_CUT */
698     { OLECMDF_SUPPORTED,                  exec_copy                 }, /* OLECMDID_COPY */
699     { OLECMDF_SUPPORTED,                  exec_paste                }, /* OLECMDID_PASTE */
700     { OLECMDF_SUPPORTED,                  exec_paste_special        }, /* OLECMDID_PASTESPECIAL */
701     { OLECMDF_SUPPORTED,                  exec_undo                 }, /* OLECMDID_UNDO */
702     { OLECMDF_SUPPORTED,                  exec_rendo                }, /* OLECMDID_REDO */
703     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_select_all           }, /* OLECMDID_SELECTALL */
704     { OLECMDF_SUPPORTED,                  exec_clear_selection      }, /* OLECMDID_CLEARSELECTION */
705     { OLECMDF_SUPPORTED,                  exec_zoom                 }, /* OLECMDID_ZOOM */
706     { OLECMDF_SUPPORTED,                  exec_get_zoom_range       }, /* OLECMDID_GETZOOMRANGE */
707     {0},
708     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_refresh              }, /* OLECMDID_REFRESH */
709     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_stop                 }, /* OLECMDID_STOP */
710     {0},{0},{0},{0},{0},{0},
711     { OLECMDF_SUPPORTED,                  exec_stop_download        }, /* OLECMDID_STOPDOWNLOAD */
712     {0},{0},
713     { OLECMDF_SUPPORTED,                  exec_delete               }, /* OLECMDID_DELETE */
714     {0},{0},
715     { OLECMDF_SUPPORTED,                  exec_enable_interaction   }, /* OLECMDID_ENABLE_INTERACTION */
716     { OLECMDF_SUPPORTED,                  exec_on_unload            }, /* OLECMDID_ONUNLOAD */
717     {0},{0},{0},{0},{0},
718     { OLECMDF_SUPPORTED,                  exec_show_page_setup      }, /* OLECMDID_SHOWPAGESETUP */
719     { OLECMDF_SUPPORTED,                  exec_show_print           }, /* OLECMDID_SHOWPRINT */
720     {0},{0},
721     { OLECMDF_SUPPORTED,                  exec_close                }, /* OLECMDID_CLOSE */
722     {0},{0},{0},
723     { OLECMDF_SUPPORTED,                  exec_set_print_template   }, /* OLECMDID_SETPRINTTEMPLATE */
724     { OLECMDF_SUPPORTED,                  exec_get_print_template   }  /* OLECMDID_GETPRINTTEMPLATE */
725 };
726
727 static HRESULT WINAPI OleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
728 {
729     HTMLDocument *This = CMDTARGET_THIS(iface);
730     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
731 }
732
733 static ULONG WINAPI OleCommandTarget_AddRef(IOleCommandTarget *iface)
734 {
735     HTMLDocument *This = CMDTARGET_THIS(iface);
736     return IHTMLDocument2_AddRef(HTMLDOC(This));
737 }
738
739 static ULONG WINAPI OleCommandTarget_Release(IOleCommandTarget *iface)
740 {
741     HTMLDocument *This = CMDTARGET_THIS(iface);
742     return IHTMLDocument_Release(HTMLDOC(This));
743 }
744
745 static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
746         ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
747 {
748     HTMLDocument *This = CMDTARGET_THIS(iface);
749     HRESULT hres = S_OK, hr;
750
751     TRACE("(%p)->(%s %ld %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
752
753     if(!pguidCmdGroup) {
754         ULONG i;
755
756         for(i=0; i<cCmds; i++) {
757             if(prgCmds[i].cmdID<OLECMDID_OPEN || prgCmds[i].cmdID>OLECMDID_GETPRINTTEMPLATE) {
758                 WARN("Unsupported cmdID = %ld\n", prgCmds[i].cmdID);
759                 prgCmds[i].cmdf = 0;
760                 hres = OLECMDERR_E_NOTSUPPORTED;
761             }else {
762                 if(prgCmds[i].cmdID == OLECMDID_OPEN || prgCmds[i].cmdID == OLECMDID_NEW) {
763                     IOleCommandTarget *cmdtrg = NULL;
764                     OLECMD olecmd;
765
766                     prgCmds[i].cmdf = OLECMDF_SUPPORTED;
767                     if(This->client) {
768                         hr = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget,
769                                 (void**)&cmdtrg);
770                         if(SUCCEEDED(hr)) {
771                             olecmd.cmdID = prgCmds[i].cmdID;
772                             olecmd.cmdf = 0;
773
774                             hr = IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &olecmd, NULL);
775                             if(SUCCEEDED(hr) && olecmd.cmdf)
776                                 prgCmds[i].cmdf = olecmd.cmdf;
777                         }
778                     }else {
779                         ERR("This->client == NULL, native would crash\n");
780                     }
781                 }else {
782                     prgCmds[i].cmdf = exec_table[prgCmds[i].cmdID].cmdf;
783                     TRACE("cmdID = %ld  returning %lx\n", prgCmds[i].cmdID, prgCmds[i].cmdf);
784                 }
785                 hres = S_OK;
786             }
787         }
788
789         if(pCmdText)
790             FIXME("Set pCmdText\n");
791     }else {
792         FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
793         hres = OLECMDERR_E_UNKNOWNGROUP;
794     }
795
796     return hres;
797 }
798
799 static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
800         DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
801 {
802     HTMLDocument *This = CMDTARGET_THIS(iface);
803
804     if(!pguidCmdGroup) {
805         if(nCmdID<OLECMDID_OPEN || nCmdID>OLECMDID_GETPRINTTEMPLATE || !exec_table[nCmdID].func) {
806             WARN("Unsupported cmdID = %ld\n", nCmdID);
807             return OLECMDERR_E_NOTSUPPORTED;
808         }
809
810         return exec_table[nCmdID].func(This, nCmdexecopt, pvaIn, pvaOut);
811     }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) {
812         FIXME("unsupported nCmdID %ld of CGID_Explorer group\n", nCmdID);
813         TRACE("%p %p\n", pvaIn, pvaOut);
814         return OLECMDERR_E_NOTSUPPORTED;
815     }else if(IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup)) {
816         FIXME("unsupported nCmdID %ld of CGID_ShellDocView group\n", nCmdID);
817         return OLECMDERR_E_NOTSUPPORTED;
818     }
819
820     FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
821     return OLECMDERR_E_UNKNOWNGROUP;
822 }
823
824 #undef CMDTARGET_THIS
825
826 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
827     OleCommandTarget_QueryInterface,
828     OleCommandTarget_AddRef,
829     OleCommandTarget_Release,
830     OleCommandTarget_QueryStatus,
831     OleCommandTarget_Exec
832 };
833
834 /**********************************************************
835  * IOleControl implementation
836  */
837
838 #define CONTROL_THIS(iface) DEFINE_THIS(HTMLDocument, OleControl, iface)
839
840 static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, void **ppv)
841 {
842     HTMLDocument *This = CONTROL_THIS(iface);
843     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
844 }
845
846 static ULONG WINAPI OleControl_AddRef(IOleControl *iface)
847 {
848     HTMLDocument *This = CONTROL_THIS(iface);
849     return IHTMLDocument2_AddRef(HTMLDOC(This));
850 }
851
852 static ULONG WINAPI OleControl_Release(IOleControl *iface)
853 {
854     HTMLDocument *This = CONTROL_THIS(iface);
855     return IHTMLDocument_Release(HTMLDOC(This));
856 }
857
858 static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, CONTROLINFO *pCI)
859 {
860     HTMLDocument *This = CONTROL_THIS(iface);
861     FIXME("(%p)->(%p)\n", This, pCI);
862     return E_NOTIMPL;
863 }
864
865 static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, MSG *pMsg)
866 {
867     HTMLDocument *This = CONTROL_THIS(iface);
868     FIXME("(%p)->(%p)\n", This, pMsg);
869     return E_NOTIMPL;
870 }
871
872 static HRESULT get_property(IOleClientSite *client, DISPID dispid, VARIANT *res)
873 {
874     IDispatch *disp = NULL;
875     DISPPARAMS dispparams = {NULL, 0};
876     UINT err;
877     HRESULT hres;
878
879     hres = IOleClientSite_QueryInterface(client, &IID_IDispatch, (void**)&disp);
880     if(FAILED(hres)) {
881         TRACE("Could not get IDispatch\n");
882         return hres;
883     }
884
885     VariantInit(res);
886
887     hres = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
888             DISPATCH_PROPERTYGET, &dispparams, res, NULL, &err);
889
890     IDispatch_Release(disp);
891
892     return hres;
893 }
894
895 static HRESULT on_change_dlcontrol(HTMLDocument *This)
896 {
897     VARIANT res;
898     HRESULT hres;
899     
900     hres = get_property(This->client, DISPID_AMBIENT_DLCONTROL, &res);
901     if(SUCCEEDED(hres))
902         FIXME("unsupported dlcontrol %08lx\n", V_I4(&res));
903
904     return S_OK;
905 }
906
907 static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID)
908 {
909     HTMLDocument *This = CONTROL_THIS(iface);
910     VARIANT res;
911     HRESULT hres;
912
913     if(!This->client) {
914         TRACE("This->client = NULL\n");
915         return S_OK;
916     }
917
918     switch(dispID) {
919     case DISPID_AMBIENT_USERMODE:
920         TRACE("(%p)->(DISPID_AMBIENT_USERMODE)\n", This);
921         hres = get_property(This->client, DISPID_AMBIENT_USERMODE, &res);
922         if(FAILED(hres))
923             return S_OK;
924
925         if(V_VT(&res) == VT_BOOL) {
926             if(!V_BOOL(&res)) {
927                 FIXME("edit mode is not supported\n");
928                 hres = E_FAIL;
929             }
930         }else {
931             FIXME("V_VT(res)=%d\n", V_VT(&res));
932         }
933         return S_OK;
934     case DISPID_AMBIENT_DLCONTROL:
935         TRACE("(%p)->(DISPID_AMBIENT_DLCONTROL)\n", This);
936         return on_change_dlcontrol(This);
937     case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
938         TRACE("(%p)->(DISPID_AMBIENT_OFFLINEIFNOTCONNECTED)\n", This);
939         on_change_dlcontrol(This);
940         hres = get_property(This->client, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &res);
941         if(FAILED(hres))
942             return S_OK;
943
944         if(V_VT(&res) == VT_BOOL) {
945             if(V_BOOL(&res)) {
946                 FIXME("offline connection is not supported\n");
947                 hres = E_FAIL;
948             }
949         }else {
950             FIXME("V_VT(res)=%d\n", V_VT(&res));
951         }
952         return S_OK;
953     case DISPID_AMBIENT_SILENT:
954         TRACE("(%p)->(DISPID_AMBIENT_SILENT)\n", This);
955         on_change_dlcontrol(This);
956         hres = get_property(This->client, DISPID_AMBIENT_SILENT, &res);
957         if(FAILED(hres))
958             return S_OK;
959
960         if(V_VT(&res) == VT_BOOL) {
961             if(V_BOOL(&res)) {
962                 FIXME("silent mode is not supported\n");
963                 hres = E_FAIL;
964             }
965         }else {
966             FIXME("V_VT(res)=%d\n", V_VT(&res));
967         }
968         return S_OK;
969     case DISPID_AMBIENT_USERAGENT:
970         TRACE("(%p)->(DISPID_AMBIENT_USERAGENT)\n", This);
971         hres = get_property(This->client, DISPID_AMBIENT_USERAGENT, &res);
972         if(FAILED(hres))
973             return S_OK;
974
975         FIXME("not supported AMBIENT_USERAGENT\n");
976         hres = E_FAIL;
977         return S_OK;
978     case DISPID_AMBIENT_PALETTE:
979         TRACE("(%p)->(DISPID_AMBIENT_PALETTE)\n", This);
980         hres = get_property(This->client, DISPID_AMBIENT_PALETTE, &res);
981         if(FAILED(hres))
982             return S_OK;
983
984         FIXME("not supported AMBIENT_PALETTE\n");
985         hres = E_FAIL;
986         return S_OK;
987     }
988
989     FIXME("(%p) unsupported dispID=%ld\n", This, dispID);
990     return E_FAIL;
991 }
992
993 static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze)
994 {
995     HTMLDocument *This = CONTROL_THIS(iface);
996     FIXME("(%p)->(%x)\n", This, bFreeze);
997     return E_NOTIMPL;
998 }
999
1000 #undef CONTROL_THIS
1001
1002 static const IOleControlVtbl OleControlVtbl = {
1003     OleControl_QueryInterface,
1004     OleControl_AddRef,
1005     OleControl_Release,
1006     OleControl_GetControlInfo,
1007     OleControl_OnMnemonic,
1008     OleControl_OnAmbientPropertyChange,
1009     OleControl_FreezeEvents
1010 };
1011
1012 void HTMLDocument_LockContainer(HTMLDocument *This, BOOL fLock)
1013 {
1014     IOleContainer *container;
1015     HRESULT hres;
1016
1017     if(!This->client || This->container_locked == fLock)
1018         return;
1019
1020     hres = IOleClientSite_GetContainer(This->client, &container);
1021     if(SUCCEEDED(hres)) {
1022         IOleContainer_LockContainer(container, fLock);
1023         This->container_locked = fLock;
1024         IOleContainer_Release(container);
1025     }
1026 }
1027
1028 void HTMLDocument_OleObj_Init(HTMLDocument *This)
1029 {
1030     This->lpOleObjectVtbl = &OleObjectVtbl;
1031     This->lpOleDocumentVtbl = &OleDocumentVtbl;
1032     This->lpOleCommandTargetVtbl = &OleCommandTargetVtbl;
1033     This->lpOleControlVtbl = &OleControlVtbl;
1034
1035     This->client = NULL;
1036     This->hostui = NULL;
1037
1038     This->has_key_path = FALSE;
1039     This->container_locked = FALSE;
1040 }