mshtml: Use heap_alloc_zero to allocate OmNavigator.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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     VARIANT silent;
70     HRESULT hres;
71
72     TRACE("(%p)->(%p)\n", This, pClientSite);
73
74     if(pClientSite == This->client)
75         return S_OK;
76
77     if(This->client) {
78         IOleClientSite_Release(This->client);
79         This->client = NULL;
80         This->usermode = UNKNOWN_USERMODE;
81     }
82
83     if(This->hostui) {
84         IDocHostUIHandler_Release(This->hostui);
85         This->hostui = NULL;
86     }
87
88     memset(&This->hostinfo, 0, sizeof(DOCHOSTUIINFO));
89
90     if(!pClientSite)
91         return S_OK;
92
93     hres = IOleObject_QueryInterface(pClientSite, &IID_IDocHostUIHandler, (void**)&pDocHostUIHandler);
94     if(SUCCEEDED(hres)) {
95         DOCHOSTUIINFO hostinfo;
96         LPOLESTR key_path = NULL, override_key_path = NULL;
97         IDocHostUIHandler2 *pDocHostUIHandler2;
98
99         memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
100         hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
101         hres = IDocHostUIHandler_GetHostInfo(pDocHostUIHandler, &hostinfo);
102         if(SUCCEEDED(hres)) {
103             TRACE("hostinfo = {%u %08x %08x %s %s}\n",
104                     hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
105                     debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
106             This->hostinfo = hostinfo;
107         }
108
109         if(!This->has_key_path) {
110             hres = IDocHostUIHandler_GetOptionKeyPath(pDocHostUIHandler, &key_path, 0);
111             if(hres == S_OK && key_path) {
112                 if(key_path[0]) {
113                     /* FIXME: use key_path */
114                     TRACE("key_path = %s\n", debugstr_w(key_path));
115                 }
116                 CoTaskMemFree(key_path);
117             }
118
119             hres = IDocHostUIHandler_QueryInterface(pDocHostUIHandler, &IID_IDocHostUIHandler2,
120                     (void**)&pDocHostUIHandler2);
121             if(SUCCEEDED(hres)) {
122                 hres = IDocHostUIHandler2_GetOverrideKeyPath(pDocHostUIHandler2, &override_key_path, 0);
123                 if(hres == S_OK && override_key_path && override_key_path[0]) {
124                     if(override_key_path[0]) {
125                         /*FIXME: use override_key_path */
126                         TRACE("override_key_path = %s\n", debugstr_w(override_key_path));
127                     }
128                     CoTaskMemFree(override_key_path);
129                 }
130                 IDocHostUIHandler2_Release(pDocHostUIHandler2);
131             }
132
133             This->has_key_path = TRUE;
134         }
135     }
136
137     /* Native calls here GetWindow. What is it for?
138      * We don't have anything to do with it here (yet). */
139     if(pClientSite) {
140         IOleWindow *pOleWindow = NULL;
141         HWND hwnd;
142
143         hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleWindow, (void**)&pOleWindow);
144         if(SUCCEEDED(hres)) {
145             IOleWindow_GetWindow(pOleWindow, &hwnd);
146             IOleWindow_Release(pOleWindow);
147         }
148     }
149
150     hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleCommandTarget, (void**)&cmdtrg);
151     if(SUCCEEDED(hres)) {
152         VARIANT var;
153         OLECMD cmd = {OLECMDID_SETPROGRESSTEXT, 0};
154
155         IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &cmd, NULL);
156
157         V_VT(&var) = VT_I4;
158         V_I4(&var) = 0;
159         IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSMAX,
160                 OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL);
161         IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSPOS, 
162                 OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL);
163
164         IOleCommandTarget_Release(cmdtrg);
165     }
166
167     IOleClientSite_AddRef(pClientSite);
168     This->client = pClientSite;
169     This->hostui = pDocHostUIHandler;
170
171     if(This->usermode == UNKNOWN_USERMODE)
172         IOleControl_OnAmbientPropertyChange(CONTROL(This), DISPID_AMBIENT_USERMODE);
173
174     IOleControl_OnAmbientPropertyChange(CONTROL(This), DISPID_AMBIENT_OFFLINEIFNOTCONNECTED); 
175
176     hres = get_client_disp_property(This->client, DISPID_AMBIENT_SILENT, &silent);
177     if(SUCCEEDED(hres)) {
178         if(V_VT(&silent) != VT_BOOL)
179             WARN("V_VT(silent) = %d\n", V_VT(&silent));
180         else if(V_BOOL(&silent))
181             FIXME("silent == true\n");
182     }
183
184     IOleControl_OnAmbientPropertyChange(CONTROL(This), DISPID_AMBIENT_USERAGENT);
185     IOleControl_OnAmbientPropertyChange(CONTROL(This), DISPID_AMBIENT_PALETTE);
186
187     return S_OK;
188 }
189
190 static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, IOleClientSite **ppClientSite)
191 {
192     HTMLDocument *This = OLEOBJ_THIS(iface);
193
194     TRACE("(%p)->(%p)\n", This, ppClientSite);
195
196     if(!ppClientSite)
197         return E_INVALIDARG;
198
199     if(This->client)
200         IOleClientSite_AddRef(This->client);
201     *ppClientSite = This->client;
202
203     return S_OK;
204 }
205
206 static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
207 {
208     HTMLDocument *This = OLEOBJ_THIS(iface);
209     FIXME("(%p)->(%s %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj));
210     return E_NOTIMPL;
211 }
212
213 static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption)
214 {
215     HTMLDocument *This = OLEOBJ_THIS(iface);
216
217     TRACE("(%p)->(%08x)\n", This, dwSaveOption);
218
219     if(dwSaveOption == OLECLOSE_PROMPTSAVE)
220         FIXME("OLECLOSE_PROMPTSAVE not implemented\n");
221
222     if(This->in_place_active)
223         IOleInPlaceObjectWindowless_InPlaceDeactivate(INPLACEWIN(This));
224
225     HTMLDocument_LockContainer(This, FALSE);
226     
227     return S_OK;
228 }
229
230 static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker *pmk)
231 {
232     HTMLDocument *This = OLEOBJ_THIS(iface);
233     FIXME("(%p %d %p)->()\n", This, dwWhichMoniker, pmk);
234     return E_NOTIMPL;
235 }
236
237 static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
238 {
239     HTMLDocument *This = OLEOBJ_THIS(iface);
240     FIXME("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
241     return E_NOTIMPL;
242 }
243
244 static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, IDataObject *pDataObject, BOOL fCreation,
245                                         DWORD dwReserved)
246 {
247     HTMLDocument *This = OLEOBJ_THIS(iface);
248     FIXME("(%p)->(%p %x %d)\n", This, pDataObject, fCreation, dwReserved);
249     return E_NOTIMPL;
250 }
251
252 static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved, IDataObject **ppDataObject)
253 {
254     HTMLDocument *This = OLEOBJ_THIS(iface);
255     FIXME("(%p)->(%d %p)\n", This, dwReserved, ppDataObject);
256     return E_NOTIMPL;
257 }
258
259 static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite,
260                                         LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
261 {
262     HTMLDocument *This = OLEOBJ_THIS(iface);
263     IOleDocumentSite *pDocSite;
264     HRESULT hres;
265
266     TRACE("(%p)->(%d %p %p %d %p %p)\n", This, iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect);
267
268     if(iVerb != OLEIVERB_SHOW && iVerb != OLEIVERB_UIACTIVATE && iVerb != OLEIVERB_INPLACEACTIVATE) { 
269         FIXME("iVerb = %d not supported\n", iVerb);
270         return E_NOTIMPL;
271     }
272
273     if(!pActiveSite)
274         pActiveSite = This->client;
275
276     hres = IOleClientSite_QueryInterface(pActiveSite, &IID_IOleDocumentSite, (void**)&pDocSite);
277     if(SUCCEEDED(hres)) {
278         HTMLDocument_LockContainer(This, TRUE);
279
280         /* FIXME: Create new IOleDocumentView. See CreateView for more info. */
281         hres = IOleDocumentSite_ActivateMe(pDocSite, DOCVIEW(This));
282         IOleDocumentSite_Release(pDocSite);
283     }else {
284         hres = IOleDocumentView_UIActivate(DOCVIEW(This), TRUE);
285         if(SUCCEEDED(hres)) {
286             if(lprcPosRect) {
287                 RECT rect; /* We need to pass rect as not const pointer */
288                 rect = *lprcPosRect;
289                 IOleDocumentView_SetRect(DOCVIEW(This), &rect);
290             }
291             IOleDocumentView_Show(DOCVIEW(This), TRUE);
292         }
293     }
294
295     return hres;
296 }
297
298 static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb)
299 {
300     HTMLDocument *This = OLEOBJ_THIS(iface);
301     FIXME("(%p)->(%p)\n", This, ppEnumOleVerb);
302     return E_NOTIMPL;
303 }
304
305 static HRESULT WINAPI OleObject_Update(IOleObject *iface)
306 {
307     HTMLDocument *This = OLEOBJ_THIS(iface);
308     FIXME("(%p)\n", This);
309     return E_NOTIMPL;
310 }
311
312 static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface)
313 {
314     HTMLDocument *This = OLEOBJ_THIS(iface);
315     FIXME("(%p)\n", This);
316     return E_NOTIMPL;
317 }
318
319 static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID *pClsid)
320 {
321     HTMLDocument *This = OLEOBJ_THIS(iface);
322
323     TRACE("(%p)->(%p)\n", This, pClsid);
324
325     if(!pClsid)
326         return E_INVALIDARG;
327
328     *pClsid = CLSID_HTMLDocument;
329     return S_OK;
330 }
331
332 static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType, LPOLESTR *pszUserType)
333 {
334     HTMLDocument *This = OLEOBJ_THIS(iface);
335     FIXME("(%p)->(%d %p)\n", This, dwFormOfType, pszUserType);
336     return E_NOTIMPL;
337 }
338
339 static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
340 {
341     HTMLDocument *This = OLEOBJ_THIS(iface);
342     FIXME("(%p)->(%d %p)\n", This, dwDrawAspect, psizel);
343     return E_NOTIMPL;
344 }
345
346 static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
347 {
348     HTMLDocument *This = OLEOBJ_THIS(iface);
349     FIXME("(%p)->(%d %p)\n", This, dwDrawAspect, psizel);
350     return E_NOTIMPL;
351 }
352
353 static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink, DWORD *pdwConnection)
354 {
355     HTMLDocument *This = OLEOBJ_THIS(iface);
356     FIXME("(%p)->(%p %p)\n", This, pAdvSink, pdwConnection);
357     return E_NOTIMPL;
358 }
359
360 static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection)
361 {
362     HTMLDocument *This = OLEOBJ_THIS(iface);
363     FIXME("(%p)->(%d)\n", This, dwConnection);
364     return E_NOTIMPL;
365 }
366
367 static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise)
368 {
369     HTMLDocument *This = OLEOBJ_THIS(iface);
370     FIXME("(%p)->(%p)\n", This, ppenumAdvise);
371     return E_NOTIMPL;
372 }
373
374 static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus)
375 {
376     HTMLDocument *This = OLEOBJ_THIS(iface);
377     FIXME("(%p)->(%d %p)\n", This, dwAspect, pdwStatus);
378     return E_NOTIMPL;
379 }
380
381 static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE *pLogpal)
382 {
383     HTMLDocument *This = OLEOBJ_THIS(iface);
384     FIXME("(%p)->(%p)\n", This, pLogpal);
385     return E_NOTIMPL;
386 }
387
388 #undef OLEPBJ_THIS
389
390 static const IOleObjectVtbl OleObjectVtbl = {
391     OleObject_QueryInterface,
392     OleObject_AddRef,
393     OleObject_Release,
394     OleObject_SetClientSite,
395     OleObject_GetClientSite,
396     OleObject_SetHostNames,
397     OleObject_Close,
398     OleObject_SetMoniker,
399     OleObject_GetMoniker,
400     OleObject_InitFromData,
401     OleObject_GetClipboardData,
402     OleObject_DoVerb,
403     OleObject_EnumVerbs,
404     OleObject_Update,
405     OleObject_IsUpToDate,
406     OleObject_GetUserClassID,
407     OleObject_GetUserType,
408     OleObject_SetExtent,
409     OleObject_GetExtent,
410     OleObject_Advise,
411     OleObject_Unadvise,
412     OleObject_EnumAdvise,
413     OleObject_GetMiscStatus,
414     OleObject_SetColorScheme
415 };
416
417 /**********************************************************
418  * IOleDocument implementation
419  */
420
421 #define OLEDOC_THIS(iface) DEFINE_THIS(HTMLDocument, OleDocument, iface)
422
423 static HRESULT WINAPI OleDocument_QueryInterface(IOleDocument *iface, REFIID riid, void **ppvObject)
424 {
425     HTMLDocument *This = OLEDOC_THIS(iface);
426     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
427 }
428
429 static ULONG WINAPI OleDocument_AddRef(IOleDocument *iface)
430 {
431     HTMLDocument *This = OLEDOC_THIS(iface);
432     return IHTMLDocument2_AddRef(HTMLDOC(This));
433 }
434
435 static ULONG WINAPI OleDocument_Release(IOleDocument *iface)
436 {
437     HTMLDocument *This = OLEDOC_THIS(iface);
438     return IHTMLDocument2_Release(HTMLDOC(This));
439 }
440
441 static HRESULT WINAPI OleDocument_CreateView(IOleDocument *iface, IOleInPlaceSite *pIPSite, IStream *pstm,
442                                    DWORD dwReserved, IOleDocumentView **ppView)
443 {
444     HTMLDocument *This = OLEDOC_THIS(iface);
445     HRESULT hres;
446
447     TRACE("(%p)->(%p %p %d %p)\n", This, pIPSite, pstm, dwReserved, ppView);
448
449     if(!ppView)
450         return E_INVALIDARG;
451
452     /* FIXME:
453      * Windows implementation creates new IOleDocumentView when function is called for the
454      * first time and returns E_FAIL when it is called for the second time, but it doesn't matter
455      * if the application uses returned interfaces, passed to ActivateMe or returned by
456      * QueryInterface, so there is no reason to create new interface. This needs more testing.
457      */
458
459     if(pIPSite) {
460         hres = IOleDocumentView_SetInPlaceSite(DOCVIEW(This), pIPSite);
461         if(FAILED(hres))
462             return hres;
463     }
464
465     if(pstm)
466         FIXME("pstm is not supported\n");
467
468     IOleDocumentView_AddRef(DOCVIEW(This));
469     *ppView = DOCVIEW(This);
470     return S_OK;
471 }
472
473 static HRESULT WINAPI OleDocument_GetDocMiscStatus(IOleDocument *iface, DWORD *pdwStatus)
474 {
475     HTMLDocument *This = OLEDOC_THIS(iface);
476     FIXME("(%p)->(%p)\n", This, pdwStatus);
477     return E_NOTIMPL;
478 }
479
480 static HRESULT WINAPI OleDocument_EnumViews(IOleDocument *iface, IEnumOleDocumentViews **ppEnum,
481                                    IOleDocumentView **ppView)
482 {
483     HTMLDocument *This = OLEDOC_THIS(iface);
484     FIXME("(%p)->(%p %p)\n", This, ppEnum, ppView);
485     return E_NOTIMPL;
486 }
487
488 #undef OLEDOC_THIS
489
490 static const IOleDocumentVtbl OleDocumentVtbl = {
491     OleDocument_QueryInterface,
492     OleDocument_AddRef,
493     OleDocument_Release,
494     OleDocument_CreateView,
495     OleDocument_GetDocMiscStatus,
496     OleDocument_EnumViews
497 };
498
499 /**********************************************************
500  * IOleControl implementation
501  */
502
503 #define CONTROL_THIS(iface) DEFINE_THIS(HTMLDocument, OleControl, iface)
504
505 static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, void **ppv)
506 {
507     HTMLDocument *This = CONTROL_THIS(iface);
508     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
509 }
510
511 static ULONG WINAPI OleControl_AddRef(IOleControl *iface)
512 {
513     HTMLDocument *This = CONTROL_THIS(iface);
514     return IHTMLDocument2_AddRef(HTMLDOC(This));
515 }
516
517 static ULONG WINAPI OleControl_Release(IOleControl *iface)
518 {
519     HTMLDocument *This = CONTROL_THIS(iface);
520     return IHTMLDocument_Release(HTMLDOC(This));
521 }
522
523 static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, CONTROLINFO *pCI)
524 {
525     HTMLDocument *This = CONTROL_THIS(iface);
526     FIXME("(%p)->(%p)\n", This, pCI);
527     return E_NOTIMPL;
528 }
529
530 static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, MSG *pMsg)
531 {
532     HTMLDocument *This = CONTROL_THIS(iface);
533     FIXME("(%p)->(%p)\n", This, pMsg);
534     return E_NOTIMPL;
535 }
536
537 HRESULT get_client_disp_property(IOleClientSite *client, DISPID dispid, VARIANT *res)
538 {
539     IDispatch *disp = NULL;
540     DISPPARAMS dispparams = {NULL, 0};
541     UINT err;
542     HRESULT hres;
543
544     hres = IOleClientSite_QueryInterface(client, &IID_IDispatch, (void**)&disp);
545     if(FAILED(hres)) {
546         TRACE("Could not get IDispatch\n");
547         return hres;
548     }
549
550     VariantInit(res);
551
552     hres = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
553             DISPATCH_PROPERTYGET, &dispparams, res, NULL, &err);
554
555     IDispatch_Release(disp);
556
557     return hres;
558 }
559
560 static HRESULT on_change_dlcontrol(HTMLDocument *This)
561 {
562     VARIANT res;
563     HRESULT hres;
564     
565     hres = get_client_disp_property(This->client, DISPID_AMBIENT_DLCONTROL, &res);
566     if(SUCCEEDED(hres))
567         FIXME("unsupported dlcontrol %08x\n", V_I4(&res));
568
569     return S_OK;
570 }
571
572 static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID)
573 {
574     HTMLDocument *This = CONTROL_THIS(iface);
575     VARIANT res;
576     HRESULT hres;
577
578     if(!This->client) {
579         TRACE("This->client = NULL\n");
580         return S_OK;
581     }
582
583     switch(dispID) {
584     case DISPID_AMBIENT_USERMODE:
585         TRACE("(%p)->(DISPID_AMBIENT_USERMODE)\n", This);
586         hres = get_client_disp_property(This->client, DISPID_AMBIENT_USERMODE, &res);
587         if(FAILED(hres))
588             return S_OK;
589
590         if(V_VT(&res) == VT_BOOL) {
591             if(V_BOOL(&res)) {
592                 This->usermode = BROWSEMODE;
593             }else {
594                 FIXME("edit mode is not supported\n");
595                 This->usermode = EDITMODE;
596             }
597         }else {
598             FIXME("V_VT(res)=%d\n", V_VT(&res));
599         }
600         return S_OK;
601     case DISPID_AMBIENT_DLCONTROL:
602         TRACE("(%p)->(DISPID_AMBIENT_DLCONTROL)\n", This);
603         return on_change_dlcontrol(This);
604     case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
605         TRACE("(%p)->(DISPID_AMBIENT_OFFLINEIFNOTCONNECTED)\n", This);
606         on_change_dlcontrol(This);
607         hres = get_client_disp_property(This->client, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &res);
608         if(FAILED(hres))
609             return S_OK;
610
611         if(V_VT(&res) == VT_BOOL) {
612             if(V_BOOL(&res)) {
613                 FIXME("offline connection is not supported\n");
614                 hres = E_FAIL;
615             }
616         }else {
617             FIXME("V_VT(res)=%d\n", V_VT(&res));
618         }
619         return S_OK;
620     case DISPID_AMBIENT_SILENT:
621         TRACE("(%p)->(DISPID_AMBIENT_SILENT)\n", This);
622         on_change_dlcontrol(This);
623         hres = get_client_disp_property(This->client, DISPID_AMBIENT_SILENT, &res);
624         if(FAILED(hres))
625             return S_OK;
626
627         if(V_VT(&res) == VT_BOOL) {
628             if(V_BOOL(&res)) {
629                 FIXME("silent mode is not supported\n");
630                 hres = E_FAIL;
631             }
632         }else {
633             FIXME("V_VT(res)=%d\n", V_VT(&res));
634         }
635         return S_OK;
636     case DISPID_AMBIENT_USERAGENT:
637         TRACE("(%p)->(DISPID_AMBIENT_USERAGENT)\n", This);
638         hres = get_client_disp_property(This->client, DISPID_AMBIENT_USERAGENT, &res);
639         if(FAILED(hres))
640             return S_OK;
641
642         FIXME("not supported AMBIENT_USERAGENT\n");
643         hres = E_FAIL;
644         return S_OK;
645     case DISPID_AMBIENT_PALETTE:
646         TRACE("(%p)->(DISPID_AMBIENT_PALETTE)\n", This);
647         hres = get_client_disp_property(This->client, DISPID_AMBIENT_PALETTE, &res);
648         if(FAILED(hres))
649             return S_OK;
650
651         FIXME("not supported AMBIENT_PALETTE\n");
652         hres = E_FAIL;
653         return S_OK;
654     }
655
656     FIXME("(%p) unsupported dispID=%d\n", This, dispID);
657     return E_FAIL;
658 }
659
660 static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze)
661 {
662     HTMLDocument *This = CONTROL_THIS(iface);
663     FIXME("(%p)->(%x)\n", This, bFreeze);
664     return E_NOTIMPL;
665 }
666
667 #undef CONTROL_THIS
668
669 static const IOleControlVtbl OleControlVtbl = {
670     OleControl_QueryInterface,
671     OleControl_AddRef,
672     OleControl_Release,
673     OleControl_GetControlInfo,
674     OleControl_OnMnemonic,
675     OleControl_OnAmbientPropertyChange,
676     OleControl_FreezeEvents
677 };
678
679 /**********************************************************
680  * ICustomDoc implementation
681  */
682
683 #define CUSTOMDOC_THIS(iface) DEFINE_THIS(HTMLDocument, CustomDoc, iface)
684
685 static HRESULT WINAPI CustomDoc_QueryInterface(ICustomDoc *iface, REFIID riid, void **ppv)
686 {
687     HTMLDocument *This = CUSTOMDOC_THIS(iface);
688     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
689 }
690
691 static ULONG WINAPI CustomDoc_AddRef(ICustomDoc *iface)
692 {
693     HTMLDocument *This = CUSTOMDOC_THIS(iface);
694     return IHTMLDocument2_AddRef(HTMLDOC(This));
695 }
696
697 static ULONG WINAPI CustomDoc_Release(ICustomDoc *iface)
698 {
699     HTMLDocument *This = CUSTOMDOC_THIS(iface);
700     return IHTMLDocument_Release(HTMLDOC(This));
701 }
702
703 static HRESULT WINAPI CustomDoc_SetUIHandler(ICustomDoc *iface, IDocHostUIHandler *pUIHandler)
704 {
705     HTMLDocument *This = CUSTOMDOC_THIS(iface);
706     FIXME("(%p)->(%p)\n", This, pUIHandler);
707     return E_NOTIMPL;
708 }
709
710 #undef CUSTOMDOC_THIS
711
712 static const ICustomDocVtbl CustomDocVtbl = {
713     CustomDoc_QueryInterface,
714     CustomDoc_AddRef,
715     CustomDoc_Release,
716     CustomDoc_SetUIHandler
717 };
718
719 void HTMLDocument_LockContainer(HTMLDocument *This, BOOL fLock)
720 {
721     IOleContainer *container;
722     HRESULT hres;
723
724     if(!This->client || This->container_locked == fLock)
725         return;
726
727     hres = IOleClientSite_GetContainer(This->client, &container);
728     if(SUCCEEDED(hres)) {
729         IOleContainer_LockContainer(container, fLock);
730         This->container_locked = fLock;
731         IOleContainer_Release(container);
732     }
733 }
734
735 void HTMLDocument_OleObj_Init(HTMLDocument *This)
736 {
737     This->lpOleObjectVtbl = &OleObjectVtbl;
738     This->lpOleDocumentVtbl = &OleDocumentVtbl;
739     This->lpOleControlVtbl = &OleControlVtbl;
740     This->lpCustomDocVtbl = &CustomDocVtbl;
741
742     This->usermode = UNKNOWN_USERMODE;
743
744     This->client = NULL;
745     This->hostui = NULL;
746
747     This->has_key_path = FALSE;
748     This->container_locked = FALSE;
749
750     memset(&This->hostinfo, 0, sizeof(DOCHOSTUIINFO));
751 }