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