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