xref: /reactos/dll/win32/mshtml/oleobj.c (revision 8a978a17)
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 "mshtml_private.h"
20 
21 #define DOCHOST_DOCCANNAVIGATE  0
22 
23 typedef struct {
24     IEnumUnknown IEnumUnknown_iface;
25     LONG ref;
26 } EnumUnknown;
27 
28 static inline EnumUnknown *impl_from_IEnumUnknown(IEnumUnknown *iface)
29 {
30     return CONTAINING_RECORD(iface, EnumUnknown, IEnumUnknown_iface);
31 }
32 
33 static HRESULT WINAPI EnumUnknown_QueryInterface(IEnumUnknown *iface, REFIID riid, void **ppv)
34 {
35     EnumUnknown *This = impl_from_IEnumUnknown(iface);
36 
37     if(IsEqualGUID(&IID_IUnknown, riid)) {
38         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
39         *ppv = &This->IEnumUnknown_iface;
40     }else if(IsEqualGUID(&IID_IEnumUnknown, riid)) {
41         TRACE("(%p)->(IID_IEnumUnknown %p)\n", This, ppv);
42         *ppv = &This->IEnumUnknown_iface;
43     }else {
44         WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
45         *ppv = NULL;
46         return E_NOINTERFACE;
47     }
48 
49     IUnknown_AddRef((IUnknown*)*ppv);
50     return S_OK;
51 }
52 
53 static ULONG WINAPI EnumUnknown_AddRef(IEnumUnknown *iface)
54 {
55     EnumUnknown *This = impl_from_IEnumUnknown(iface);
56     LONG ref = InterlockedIncrement(&This->ref);
57 
58     TRACE("(%p) ref=%d\n", This, ref);
59 
60     return ref;
61 }
62 
63 static ULONG WINAPI EnumUnknown_Release(IEnumUnknown *iface)
64 {
65     EnumUnknown *This = impl_from_IEnumUnknown(iface);
66     LONG ref = InterlockedDecrement(&This->ref);
67 
68     TRACE("(%p) ref=%d\n", This, ref);
69 
70     if(!ref)
71         heap_free(This);
72 
73     return ref;
74 }
75 
76 static HRESULT WINAPI EnumUnknown_Next(IEnumUnknown *iface, ULONG celt, IUnknown **rgelt, ULONG *pceltFetched)
77 {
78     EnumUnknown *This = impl_from_IEnumUnknown(iface);
79 
80     TRACE("(%p)->(%u %p %p)\n", This, celt, rgelt, pceltFetched);
81 
82     /* FIXME: It's not clear if we should ever return something here */
83     if(pceltFetched)
84         *pceltFetched = 0;
85     return S_FALSE;
86 }
87 
88 static HRESULT WINAPI EnumUnknown_Skip(IEnumUnknown *iface, ULONG celt)
89 {
90     EnumUnknown *This = impl_from_IEnumUnknown(iface);
91     FIXME("(%p)->(%u)\n", This, celt);
92     return E_NOTIMPL;
93 }
94 
95 static HRESULT WINAPI EnumUnknown_Reset(IEnumUnknown *iface)
96 {
97     EnumUnknown *This = impl_from_IEnumUnknown(iface);
98     FIXME("(%p)\n", This);
99     return E_NOTIMPL;
100 }
101 
102 static HRESULT WINAPI EnumUnknown_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
103 {
104     EnumUnknown *This = impl_from_IEnumUnknown(iface);
105     FIXME("(%p)->(%p)\n", This, ppenum);
106     return E_NOTIMPL;
107 }
108 
109 static const IEnumUnknownVtbl EnumUnknownVtbl = {
110     EnumUnknown_QueryInterface,
111     EnumUnknown_AddRef,
112     EnumUnknown_Release,
113     EnumUnknown_Next,
114     EnumUnknown_Skip,
115     EnumUnknown_Reset,
116     EnumUnknown_Clone
117 };
118 
119 /**********************************************************
120  * IOleObject implementation
121  */
122 
123 static inline HTMLDocument *impl_from_IOleObject(IOleObject *iface)
124 {
125     return CONTAINING_RECORD(iface, HTMLDocument, IOleObject_iface);
126 }
127 
128 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv)
129 {
130     HTMLDocument *This = impl_from_IOleObject(iface);
131     return htmldoc_query_interface(This, riid, ppv);
132 }
133 
134 static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
135 {
136     HTMLDocument *This = impl_from_IOleObject(iface);
137     return htmldoc_addref(This);
138 }
139 
140 static ULONG WINAPI OleObject_Release(IOleObject *iface)
141 {
142     HTMLDocument *This = impl_from_IOleObject(iface);
143     return htmldoc_release(This);
144 }
145 
146 static void update_hostinfo(HTMLDocumentObj *This, DOCHOSTUIINFO *hostinfo)
147 {
148     nsIScrollable *scrollable;
149     nsresult nsres;
150 
151     if(!This->nscontainer)
152         return;
153 
154     nsres = nsIWebBrowser_QueryInterface(This->nscontainer->webbrowser, &IID_nsIScrollable, (void**)&scrollable);
155     if(NS_SUCCEEDED(nsres)) {
156         nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable, ScrollOrientation_Y,
157                 (hostinfo->dwFlags & DOCHOSTUIFLAG_SCROLL_NO) ? Scrollbar_Never : Scrollbar_Always);
158         if(NS_FAILED(nsres))
159             ERR("Could not set default Y scrollbar prefs: %08x\n", nsres);
160 
161         nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable, ScrollOrientation_X,
162                 hostinfo->dwFlags & DOCHOSTUIFLAG_SCROLL_NO ? Scrollbar_Never : Scrollbar_Auto);
163         if(NS_FAILED(nsres))
164             ERR("Could not set default X scrollbar prefs: %08x\n", nsres);
165 
166         nsIScrollable_Release(scrollable);
167     }else {
168         ERR("Could not get nsIScrollable: %08x\n", nsres);
169     }
170 }
171 
172 /* Calls undocumented 84 cmd of CGID_ShellDocView */
173 void call_docview_84(HTMLDocumentObj *doc)
174 {
175     IOleCommandTarget *olecmd;
176     VARIANT var;
177     HRESULT hres;
178 
179     if(!doc->client)
180         return;
181 
182     hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
183     if(FAILED(hres))
184         return;
185 
186     VariantInit(&var);
187     hres = IOleCommandTarget_Exec(olecmd, &CGID_ShellDocView, 84, 0, NULL, &var);
188     IOleCommandTarget_Release(olecmd);
189     if(SUCCEEDED(hres) && V_VT(&var) != VT_NULL)
190         FIXME("handle result\n");
191 }
192 
193 void set_document_navigation(HTMLDocumentObj *doc, BOOL doc_can_navigate)
194 {
195     VARIANT var;
196 
197     if(!doc->client_cmdtrg)
198         return;
199 
200     if(doc_can_navigate) {
201         V_VT(&var) = VT_UNKNOWN;
202         V_UNKNOWN(&var) = (IUnknown*)&doc->basedoc.window->base.IHTMLWindow2_iface;
203     }
204 
205     IOleCommandTarget_Exec(doc->client_cmdtrg, &CGID_DocHostCmdPriv, DOCHOST_DOCCANNAVIGATE, 0,
206             doc_can_navigate ? &var : NULL, NULL);
207 }
208 
209 static void load_settings(HTMLDocumentObj *doc)
210 {
211     HKEY settings_key;
212     DWORD val, size;
213     LONG res;
214 
215     static const WCHAR ie_keyW[] = {
216         'S','O','F','T','W','A','R','E','\\',
217         'M','i','c','r','o','s','o','f','t','\\',
218         'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',0};
219     static const WCHAR zoomW[] = {'Z','o','o','m',0};
220     static const WCHAR zoom_factorW[] = {'Z','o','o','m','F','a','c','t','o','r',0};
221 
222     res = RegOpenKeyW(HKEY_CURRENT_USER, ie_keyW, &settings_key);
223     if(res != ERROR_SUCCESS)
224         return;
225 
226     size = sizeof(val);
227     res = RegGetValueW(settings_key, zoomW, zoom_factorW, RRF_RT_REG_DWORD, NULL, &val, &size);
228     RegCloseKey(settings_key);
229     if(res == ERROR_SUCCESS)
230         set_viewer_zoom(doc->nscontainer, (float)val/100000);
231 }
232 
233 static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, IOleClientSite *pClientSite)
234 {
235     HTMLDocument *This = impl_from_IOleObject(iface);
236     IOleCommandTarget *cmdtrg = NULL;
237     IOleWindow *ole_window;
238     IBrowserService *browser_service;
239     BOOL hostui_setup;
240     VARIANT silent;
241     HWND hwnd;
242     HRESULT hres;
243 
244     TRACE("(%p)->(%p)\n", This, pClientSite);
245 
246     if(pClientSite == This->doc_obj->client)
247         return S_OK;
248 
249     if(This->doc_obj->client) {
250         IOleClientSite_Release(This->doc_obj->client);
251         This->doc_obj->client = NULL;
252         This->doc_obj->usermode = UNKNOWN_USERMODE;
253     }
254 
255     if(This->doc_obj->client_cmdtrg) {
256         IOleCommandTarget_Release(This->doc_obj->client_cmdtrg);
257         This->doc_obj->client_cmdtrg = NULL;
258     }
259 
260     if(This->doc_obj->hostui && !This->doc_obj->custom_hostui) {
261         IDocHostUIHandler_Release(This->doc_obj->hostui);
262         This->doc_obj->hostui = NULL;
263     }
264 
265     if(This->doc_obj->doc_object_service) {
266         IDocObjectService_Release(This->doc_obj->doc_object_service);
267         This->doc_obj->doc_object_service = NULL;
268     }
269 
270     if(This->doc_obj->webbrowser) {
271         IUnknown_Release(This->doc_obj->webbrowser);
272         This->doc_obj->webbrowser = NULL;
273     }
274 
275     if(This->doc_obj->browser_service) {
276         IUnknown_Release(This->doc_obj->browser_service);
277         This->doc_obj->browser_service = NULL;
278     }
279 
280     if(This->doc_obj->travel_log) {
281         ITravelLog_Release(This->doc_obj->travel_log);
282         This->doc_obj->travel_log = NULL;
283     }
284 
285     memset(&This->doc_obj->hostinfo, 0, sizeof(DOCHOSTUIINFO));
286 
287     if(!pClientSite)
288         return S_OK;
289 
290     IOleClientSite_AddRef(pClientSite);
291     This->doc_obj->client = pClientSite;
292 
293     hostui_setup = This->doc_obj->hostui_setup;
294 
295     if(!This->doc_obj->hostui) {
296         IDocHostUIHandler *uihandler;
297 
298         This->doc_obj->custom_hostui = FALSE;
299 
300         hres = IOleClientSite_QueryInterface(pClientSite, &IID_IDocHostUIHandler, (void**)&uihandler);
301         if(SUCCEEDED(hres))
302             This->doc_obj->hostui = uihandler;
303     }
304 
305     if(This->doc_obj->hostui) {
306         DOCHOSTUIINFO hostinfo;
307         LPOLESTR key_path = NULL, override_key_path = NULL;
308         IDocHostUIHandler2 *uihandler2;
309 
310         memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
311         hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
312         hres = IDocHostUIHandler_GetHostInfo(This->doc_obj->hostui, &hostinfo);
313         if(SUCCEEDED(hres)) {
314             TRACE("hostinfo = {%u %08x %08x %s %s}\n",
315                     hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
316                     debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
317             update_hostinfo(This->doc_obj, &hostinfo);
318             This->doc_obj->hostinfo = hostinfo;
319         }
320 
321         if(!hostui_setup) {
322             hres = IDocHostUIHandler_GetOptionKeyPath(This->doc_obj->hostui, &key_path, 0);
323             if(hres == S_OK && key_path) {
324                 if(key_path[0]) {
325                     /* FIXME: use key_path */
326                     FIXME("key_path = %s\n", debugstr_w(key_path));
327                 }
328                 CoTaskMemFree(key_path);
329             }
330 
331             hres = IDocHostUIHandler_QueryInterface(This->doc_obj->hostui, &IID_IDocHostUIHandler2,
332                     (void**)&uihandler2);
333             if(SUCCEEDED(hres)) {
334                 hres = IDocHostUIHandler2_GetOverrideKeyPath(uihandler2, &override_key_path, 0);
335                 if(hres == S_OK && override_key_path) {
336                     if(override_key_path[0]) {
337                         /*FIXME: use override_key_path */
338                         FIXME("override_key_path = %s\n", debugstr_w(override_key_path));
339                     }
340                     CoTaskMemFree(override_key_path);
341                 }
342                 IDocHostUIHandler2_Release(uihandler2);
343             }
344 
345             This->doc_obj->hostui_setup = TRUE;
346         }
347     }
348 
349     load_settings(This->doc_obj);
350 
351     /* Native calls here GetWindow. What is it for?
352      * We don't have anything to do with it here (yet). */
353     hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleWindow, (void**)&ole_window);
354     if(SUCCEEDED(hres)) {
355         IOleWindow_GetWindow(ole_window, &hwnd);
356         IOleWindow_Release(ole_window);
357     }
358 
359     hres = do_query_service((IUnknown*)pClientSite, &IID_IShellBrowser,
360             &IID_IBrowserService, (void**)&browser_service);
361     if(SUCCEEDED(hres)) {
362         ITravelLog *travel_log;
363 
364         This->doc_obj->browser_service = (IUnknown*)browser_service;
365 
366         hres = IBrowserService_GetTravelLog(browser_service, &travel_log);
367         if(SUCCEEDED(hres))
368             This->doc_obj->travel_log = travel_log;
369     }else {
370         browser_service = NULL;
371     }
372 
373     hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleCommandTarget, (void**)&cmdtrg);
374     if(SUCCEEDED(hres)) {
375         VARIANT var;
376         OLECMD cmd = {OLECMDID_SETPROGRESSTEXT, 0};
377 
378         This->doc_obj->client_cmdtrg = cmdtrg;
379 
380         if(!hostui_setup) {
381             IDocObjectService *doc_object_service;
382             IWebBrowser2 *wb;
383 
384             set_document_navigation(This->doc_obj, TRUE);
385 
386             if(browser_service) {
387                 hres = IBrowserService_QueryInterface(browser_service,
388                         &IID_IDocObjectService, (void**)&doc_object_service);
389                 if(SUCCEEDED(hres)) {
390                     This->doc_obj->doc_object_service = doc_object_service;
391 
392                     /*
393                      * Some embedding routines, esp. in regards to use of IDocObjectService, differ if
394                      * embedder supports IWebBrowserApp.
395                      */
396                     hres = do_query_service((IUnknown*)pClientSite, &IID_IWebBrowserApp, &IID_IWebBrowser2, (void**)&wb);
397                     if(SUCCEEDED(hres))
398                         This->doc_obj->webbrowser = (IUnknown*)wb;
399                 }
400             }
401         }
402 
403         call_docview_84(This->doc_obj);
404 
405         IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &cmd, NULL);
406 
407         V_VT(&var) = VT_I4;
408         V_I4(&var) = 0;
409         IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSMAX,
410                 OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL);
411         IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSPOS,
412                 OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL);
413     }
414 
415     if(This->doc_obj->usermode == UNKNOWN_USERMODE)
416         IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, DISPID_AMBIENT_USERMODE);
417 
418     IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface,
419             DISPID_AMBIENT_OFFLINEIFNOTCONNECTED);
420 
421     hres = get_client_disp_property(This->doc_obj->client, DISPID_AMBIENT_SILENT, &silent);
422     if(SUCCEEDED(hres)) {
423         if(V_VT(&silent) != VT_BOOL)
424             WARN("silent = %s\n", debugstr_variant(&silent));
425         else if(V_BOOL(&silent))
426             FIXME("silent == true\n");
427     }
428 
429     IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, DISPID_AMBIENT_USERAGENT);
430     IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, DISPID_AMBIENT_PALETTE);
431 
432     return S_OK;
433 }
434 
435 static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, IOleClientSite **ppClientSite)
436 {
437     HTMLDocument *This = impl_from_IOleObject(iface);
438 
439     TRACE("(%p)->(%p)\n", This, ppClientSite);
440 
441     if(!ppClientSite)
442         return E_INVALIDARG;
443 
444     if(This->doc_obj->client)
445         IOleClientSite_AddRef(This->doc_obj->client);
446     *ppClientSite = This->doc_obj->client;
447 
448     return S_OK;
449 }
450 
451 static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
452 {
453     HTMLDocument *This = impl_from_IOleObject(iface);
454     FIXME("(%p)->(%s %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj));
455     return E_NOTIMPL;
456 }
457 
458 static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption)
459 {
460     HTMLDocument *This = impl_from_IOleObject(iface);
461 
462     TRACE("(%p)->(%08x)\n", This, dwSaveOption);
463 
464     if(dwSaveOption == OLECLOSE_PROMPTSAVE)
465         FIXME("OLECLOSE_PROMPTSAVE not implemented\n");
466 
467     if(This->doc_obj->in_place_active)
468         IOleInPlaceObjectWindowless_InPlaceDeactivate(&This->IOleInPlaceObjectWindowless_iface);
469 
470     HTMLDocument_LockContainer(This->doc_obj, FALSE);
471 
472     if(This->advise_holder)
473         IOleAdviseHolder_SendOnClose(This->advise_holder);
474 
475     return S_OK;
476 }
477 
478 static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker *pmk)
479 {
480     HTMLDocument *This = impl_from_IOleObject(iface);
481     FIXME("(%p %d %p)->()\n", This, dwWhichMoniker, pmk);
482     return E_NOTIMPL;
483 }
484 
485 static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
486 {
487     HTMLDocument *This = impl_from_IOleObject(iface);
488     FIXME("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
489     return E_NOTIMPL;
490 }
491 
492 static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, IDataObject *pDataObject, BOOL fCreation,
493                                         DWORD dwReserved)
494 {
495     HTMLDocument *This = impl_from_IOleObject(iface);
496     FIXME("(%p)->(%p %x %d)\n", This, pDataObject, fCreation, dwReserved);
497     return E_NOTIMPL;
498 }
499 
500 static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved, IDataObject **ppDataObject)
501 {
502     HTMLDocument *This = impl_from_IOleObject(iface);
503     FIXME("(%p)->(%d %p)\n", This, dwReserved, ppDataObject);
504     return E_NOTIMPL;
505 }
506 
507 static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite,
508                                         LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
509 {
510     HTMLDocument *This = impl_from_IOleObject(iface);
511     IOleDocumentSite *pDocSite;
512     HRESULT hres;
513 
514     TRACE("(%p)->(%d %p %p %d %p %p)\n", This, iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect);
515 
516     if(iVerb != OLEIVERB_SHOW && iVerb != OLEIVERB_UIACTIVATE && iVerb != OLEIVERB_INPLACEACTIVATE) {
517         FIXME("iVerb = %d not supported\n", iVerb);
518         return E_NOTIMPL;
519     }
520 
521     if(!pActiveSite)
522         pActiveSite = This->doc_obj->client;
523 
524     hres = IOleClientSite_QueryInterface(pActiveSite, &IID_IOleDocumentSite, (void**)&pDocSite);
525     if(SUCCEEDED(hres)) {
526         HTMLDocument_LockContainer(This->doc_obj, TRUE);
527 
528         /* FIXME: Create new IOleDocumentView. See CreateView for more info. */
529         hres = IOleDocumentSite_ActivateMe(pDocSite, &This->IOleDocumentView_iface);
530         IOleDocumentSite_Release(pDocSite);
531     }else {
532         hres = IOleDocumentView_UIActivate(&This->IOleDocumentView_iface, TRUE);
533         if(SUCCEEDED(hres)) {
534             if(lprcPosRect) {
535                 RECT rect; /* We need to pass rect as not const pointer */
536                 rect = *lprcPosRect;
537                 IOleDocumentView_SetRect(&This->IOleDocumentView_iface, &rect);
538             }
539             IOleDocumentView_Show(&This->IOleDocumentView_iface, TRUE);
540         }
541     }
542 
543     return hres;
544 }
545 
546 static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb)
547 {
548     HTMLDocument *This = impl_from_IOleObject(iface);
549     FIXME("(%p)->(%p)\n", This, ppEnumOleVerb);
550     return E_NOTIMPL;
551 }
552 
553 static HRESULT WINAPI OleObject_Update(IOleObject *iface)
554 {
555     HTMLDocument *This = impl_from_IOleObject(iface);
556     FIXME("(%p)\n", This);
557     return E_NOTIMPL;
558 }
559 
560 static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface)
561 {
562     HTMLDocument *This = impl_from_IOleObject(iface);
563     FIXME("(%p)\n", This);
564     return E_NOTIMPL;
565 }
566 
567 static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID *pClsid)
568 {
569     HTMLDocument *This = impl_from_IOleObject(iface);
570 
571     TRACE("(%p)->(%p)\n", This, pClsid);
572 
573     if(!pClsid)
574         return E_INVALIDARG;
575 
576     *pClsid = CLSID_HTMLDocument;
577     return S_OK;
578 }
579 
580 static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType, LPOLESTR *pszUserType)
581 {
582     HTMLDocument *This = impl_from_IOleObject(iface);
583     FIXME("(%p)->(%d %p)\n", This, dwFormOfType, pszUserType);
584     return E_NOTIMPL;
585 }
586 
587 static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
588 {
589     HTMLDocument *This = impl_from_IOleObject(iface);
590     FIXME("(%p)->(%d %p)\n", This, dwDrawAspect, psizel);
591     return E_NOTIMPL;
592 }
593 
594 static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
595 {
596     HTMLDocument *This = impl_from_IOleObject(iface);
597     FIXME("(%p)->(%d %p)\n", This, dwDrawAspect, psizel);
598     return E_NOTIMPL;
599 }
600 
601 static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink, DWORD *pdwConnection)
602 {
603     HTMLDocument *This = impl_from_IOleObject(iface);
604     TRACE("(%p)->(%p %p)\n", This, pAdvSink, pdwConnection);
605 
606     if(!pdwConnection)
607         return E_INVALIDARG;
608 
609     if(!pAdvSink) {
610         *pdwConnection = 0;
611         return E_INVALIDARG;
612     }
613 
614     if(!This->advise_holder) {
615         CreateOleAdviseHolder(&This->advise_holder);
616         if(!This->advise_holder)
617             return E_OUTOFMEMORY;
618     }
619 
620     return IOleAdviseHolder_Advise(This->advise_holder, pAdvSink, pdwConnection);
621 }
622 
623 static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection)
624 {
625     HTMLDocument *This = impl_from_IOleObject(iface);
626     TRACE("(%p)->(%d)\n", This, dwConnection);
627 
628     if(!This->advise_holder)
629         return OLE_E_NOCONNECTION;
630 
631     return IOleAdviseHolder_Unadvise(This->advise_holder, dwConnection);
632 }
633 
634 static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise)
635 {
636     HTMLDocument *This = impl_from_IOleObject(iface);
637 
638     if(!This->advise_holder) {
639         *ppenumAdvise = NULL;
640         return S_OK;
641     }
642 
643     return IOleAdviseHolder_EnumAdvise(This->advise_holder, ppenumAdvise);
644 }
645 
646 static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus)
647 {
648     HTMLDocument *This = impl_from_IOleObject(iface);
649     FIXME("(%p)->(%d %p)\n", This, dwAspect, pdwStatus);
650     return E_NOTIMPL;
651 }
652 
653 static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE *pLogpal)
654 {
655     HTMLDocument *This = impl_from_IOleObject(iface);
656     FIXME("(%p)->(%p)\n", This, pLogpal);
657     return E_NOTIMPL;
658 }
659 
660 static const IOleObjectVtbl OleObjectVtbl = {
661     OleObject_QueryInterface,
662     OleObject_AddRef,
663     OleObject_Release,
664     OleObject_SetClientSite,
665     OleObject_GetClientSite,
666     OleObject_SetHostNames,
667     OleObject_Close,
668     OleObject_SetMoniker,
669     OleObject_GetMoniker,
670     OleObject_InitFromData,
671     OleObject_GetClipboardData,
672     OleObject_DoVerb,
673     OleObject_EnumVerbs,
674     OleObject_Update,
675     OleObject_IsUpToDate,
676     OleObject_GetUserClassID,
677     OleObject_GetUserType,
678     OleObject_SetExtent,
679     OleObject_GetExtent,
680     OleObject_Advise,
681     OleObject_Unadvise,
682     OleObject_EnumAdvise,
683     OleObject_GetMiscStatus,
684     OleObject_SetColorScheme
685 };
686 
687 /**********************************************************
688  * IOleDocument implementation
689  */
690 
691 static inline HTMLDocument *impl_from_IOleDocument(IOleDocument *iface)
692 {
693     return CONTAINING_RECORD(iface, HTMLDocument, IOleDocument_iface);
694 }
695 
696 static HRESULT WINAPI OleDocument_QueryInterface(IOleDocument *iface, REFIID riid, void **ppv)
697 {
698     HTMLDocument *This = impl_from_IOleDocument(iface);
699     return htmldoc_query_interface(This, riid, ppv);
700 }
701 
702 static ULONG WINAPI OleDocument_AddRef(IOleDocument *iface)
703 {
704     HTMLDocument *This = impl_from_IOleDocument(iface);
705     return htmldoc_addref(This);
706 }
707 
708 static ULONG WINAPI OleDocument_Release(IOleDocument *iface)
709 {
710     HTMLDocument *This = impl_from_IOleDocument(iface);
711     return htmldoc_release(This);
712 }
713 
714 static HRESULT WINAPI OleDocument_CreateView(IOleDocument *iface, IOleInPlaceSite *pIPSite, IStream *pstm,
715                                    DWORD dwReserved, IOleDocumentView **ppView)
716 {
717     HTMLDocument *This = impl_from_IOleDocument(iface);
718     HRESULT hres;
719 
720     TRACE("(%p)->(%p %p %d %p)\n", This, pIPSite, pstm, dwReserved, ppView);
721 
722     if(!ppView)
723         return E_INVALIDARG;
724 
725     /* FIXME:
726      * Windows implementation creates new IOleDocumentView when function is called for the
727      * first time and returns E_FAIL when it is called for the second time, but it doesn't matter
728      * if the application uses returned interfaces, passed to ActivateMe or returned by
729      * QueryInterface, so there is no reason to create new interface. This needs more testing.
730      */
731 
732     if(pIPSite) {
733         hres = IOleDocumentView_SetInPlaceSite(&This->IOleDocumentView_iface, pIPSite);
734         if(FAILED(hres))
735             return hres;
736     }
737 
738     if(pstm)
739         FIXME("pstm is not supported\n");
740 
741     IOleDocumentView_AddRef(&This->IOleDocumentView_iface);
742     *ppView = &This->IOleDocumentView_iface;
743     return S_OK;
744 }
745 
746 static HRESULT WINAPI OleDocument_GetDocMiscStatus(IOleDocument *iface, DWORD *pdwStatus)
747 {
748     HTMLDocument *This = impl_from_IOleDocument(iface);
749     FIXME("(%p)->(%p)\n", This, pdwStatus);
750     return E_NOTIMPL;
751 }
752 
753 static HRESULT WINAPI OleDocument_EnumViews(IOleDocument *iface, IEnumOleDocumentViews **ppEnum,
754                                    IOleDocumentView **ppView)
755 {
756     HTMLDocument *This = impl_from_IOleDocument(iface);
757     FIXME("(%p)->(%p %p)\n", This, ppEnum, ppView);
758     return E_NOTIMPL;
759 }
760 
761 static const IOleDocumentVtbl OleDocumentVtbl = {
762     OleDocument_QueryInterface,
763     OleDocument_AddRef,
764     OleDocument_Release,
765     OleDocument_CreateView,
766     OleDocument_GetDocMiscStatus,
767     OleDocument_EnumViews
768 };
769 
770 /**********************************************************
771  * IOleControl implementation
772  */
773 
774 static inline HTMLDocument *impl_from_IOleControl(IOleControl *iface)
775 {
776     return CONTAINING_RECORD(iface, HTMLDocument, IOleControl_iface);
777 }
778 
779 static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, void **ppv)
780 {
781     HTMLDocument *This = impl_from_IOleControl(iface);
782     return htmldoc_query_interface(This, riid, ppv);
783 }
784 
785 static ULONG WINAPI OleControl_AddRef(IOleControl *iface)
786 {
787     HTMLDocument *This = impl_from_IOleControl(iface);
788     return htmldoc_addref(This);
789 }
790 
791 static ULONG WINAPI OleControl_Release(IOleControl *iface)
792 {
793     HTMLDocument *This = impl_from_IOleControl(iface);
794     return htmldoc_release(This);
795 }
796 
797 static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, CONTROLINFO *pCI)
798 {
799     HTMLDocument *This = impl_from_IOleControl(iface);
800     FIXME("(%p)->(%p)\n", This, pCI);
801     return E_NOTIMPL;
802 }
803 
804 static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, MSG *pMsg)
805 {
806     HTMLDocument *This = impl_from_IOleControl(iface);
807     FIXME("(%p)->(%p)\n", This, pMsg);
808     return E_NOTIMPL;
809 }
810 
811 HRESULT get_client_disp_property(IOleClientSite *client, DISPID dispid, VARIANT *res)
812 {
813     IDispatch *disp = NULL;
814     DISPPARAMS dispparams = {NULL, 0};
815     UINT err;
816     HRESULT hres;
817 
818     hres = IOleClientSite_QueryInterface(client, &IID_IDispatch, (void**)&disp);
819     if(FAILED(hres)) {
820         TRACE("Could not get IDispatch\n");
821         return hres;
822     }
823 
824     VariantInit(res);
825 
826     hres = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
827             DISPATCH_PROPERTYGET, &dispparams, res, NULL, &err);
828 
829     IDispatch_Release(disp);
830 
831     return hres;
832 }
833 
834 static HRESULT on_change_dlcontrol(HTMLDocument *This)
835 {
836     VARIANT res;
837     HRESULT hres;
838 
839     hres = get_client_disp_property(This->doc_obj->client, DISPID_AMBIENT_DLCONTROL, &res);
840     if(SUCCEEDED(hres))
841         FIXME("unsupported dlcontrol %08x\n", V_I4(&res));
842 
843     return S_OK;
844 }
845 
846 static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID)
847 {
848     HTMLDocument *This = impl_from_IOleControl(iface);
849     IOleClientSite *client;
850     VARIANT res;
851     HRESULT hres;
852 
853     client = This->doc_obj->client;
854     if(!client) {
855         TRACE("client = NULL\n");
856         return S_OK;
857     }
858 
859     switch(dispID) {
860     case DISPID_AMBIENT_USERMODE:
861         TRACE("(%p)->(DISPID_AMBIENT_USERMODE)\n", This);
862         hres = get_client_disp_property(client, DISPID_AMBIENT_USERMODE, &res);
863         if(FAILED(hres))
864             return S_OK;
865 
866         if(V_VT(&res) == VT_BOOL) {
867             if(V_BOOL(&res)) {
868                 This->doc_obj->usermode = BROWSEMODE;
869             }else {
870                 FIXME("edit mode is not supported\n");
871                 This->doc_obj->usermode = EDITMODE;
872             }
873         }else {
874             FIXME("usermode=%s\n", debugstr_variant(&res));
875         }
876         return S_OK;
877     case DISPID_AMBIENT_DLCONTROL:
878         TRACE("(%p)->(DISPID_AMBIENT_DLCONTROL)\n", This);
879         return on_change_dlcontrol(This);
880     case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
881         TRACE("(%p)->(DISPID_AMBIENT_OFFLINEIFNOTCONNECTED)\n", This);
882         on_change_dlcontrol(This);
883         hres = get_client_disp_property(client, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &res);
884         if(FAILED(hres))
885             return S_OK;
886 
887         if(V_VT(&res) == VT_BOOL) {
888             if(V_BOOL(&res)) {
889                 FIXME("offline connection is not supported\n");
890                 hres = E_FAIL;
891             }
892         }else {
893             FIXME("offlineconnected=%s\n", debugstr_variant(&res));
894         }
895         return S_OK;
896     case DISPID_AMBIENT_SILENT:
897         TRACE("(%p)->(DISPID_AMBIENT_SILENT)\n", This);
898         on_change_dlcontrol(This);
899         hres = get_client_disp_property(client, DISPID_AMBIENT_SILENT, &res);
900         if(FAILED(hres))
901             return S_OK;
902 
903         if(V_VT(&res) == VT_BOOL) {
904             if(V_BOOL(&res)) {
905                 FIXME("silent mode is not supported\n");
906                 hres = E_FAIL;
907             }
908         }else {
909             FIXME("silent=%s\n", debugstr_variant(&res));
910         }
911         return S_OK;
912     case DISPID_AMBIENT_USERAGENT:
913         TRACE("(%p)->(DISPID_AMBIENT_USERAGENT)\n", This);
914         hres = get_client_disp_property(client, DISPID_AMBIENT_USERAGENT, &res);
915         if(FAILED(hres))
916             return S_OK;
917 
918         FIXME("not supported AMBIENT_USERAGENT\n");
919         hres = E_FAIL;
920         return S_OK;
921     case DISPID_AMBIENT_PALETTE:
922         TRACE("(%p)->(DISPID_AMBIENT_PALETTE)\n", This);
923         hres = get_client_disp_property(client, DISPID_AMBIENT_PALETTE, &res);
924         if(FAILED(hres))
925             return S_OK;
926 
927         FIXME("not supported AMBIENT_PALETTE\n");
928         hres = E_FAIL;
929         return S_OK;
930     }
931 
932     FIXME("(%p) unsupported dispID=%d\n", This, dispID);
933     return E_FAIL;
934 }
935 
936 static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze)
937 {
938     HTMLDocument *This = impl_from_IOleControl(iface);
939     FIXME("(%p)->(%x)\n", This, bFreeze);
940     return E_NOTIMPL;
941 }
942 
943 static const IOleControlVtbl OleControlVtbl = {
944     OleControl_QueryInterface,
945     OleControl_AddRef,
946     OleControl_Release,
947     OleControl_GetControlInfo,
948     OleControl_OnMnemonic,
949     OleControl_OnAmbientPropertyChange,
950     OleControl_FreezeEvents
951 };
952 
953 /**********************************************************
954  * IObjectWithSite implementation
955  */
956 
957 static inline HTMLDocument *impl_from_IObjectWithSite(IObjectWithSite *iface)
958 {
959     return CONTAINING_RECORD(iface, HTMLDocument, IObjectWithSite_iface);
960 }
961 
962 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite *iface, REFIID riid, void **ppv)
963 {
964     HTMLDocument *This = impl_from_IObjectWithSite(iface);
965     return htmldoc_query_interface(This, riid, ppv);
966 }
967 
968 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
969 {
970     HTMLDocument *This = impl_from_IObjectWithSite(iface);
971     return htmldoc_addref(This);
972 }
973 
974 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
975 {
976     HTMLDocument *This = impl_from_IObjectWithSite(iface);
977     return htmldoc_release(This);
978 }
979 
980 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite)
981 {
982     HTMLDocument *This = impl_from_IObjectWithSite(iface);
983     FIXME("(%p)->(%p)\n", This, pUnkSite);
984     return E_NOTIMPL;
985 }
986 
987 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite* iface, REFIID riid, PVOID *ppvSite)
988 {
989     HTMLDocument *This = impl_from_IObjectWithSite(iface);
990     FIXME("(%p)->(%p)\n", This, ppvSite);
991     return E_NOTIMPL;
992 }
993 
994 static const IObjectWithSiteVtbl ObjectWithSiteVtbl = {
995     ObjectWithSite_QueryInterface,
996     ObjectWithSite_AddRef,
997     ObjectWithSite_Release,
998     ObjectWithSite_SetSite,
999     ObjectWithSite_GetSite
1000 };
1001 
1002 /**********************************************************
1003  * IOleContainer implementation
1004  */
1005 
1006 static inline HTMLDocument *impl_from_IOleContainer(IOleContainer *iface)
1007 {
1008     return CONTAINING_RECORD(iface, HTMLDocument, IOleContainer_iface);
1009 }
1010 
1011 static HRESULT WINAPI OleContainer_QueryInterface(IOleContainer *iface, REFIID riid, void **ppv)
1012 {
1013     HTMLDocument *This = impl_from_IOleContainer(iface);
1014     return htmldoc_query_interface(This, riid, ppv);
1015 }
1016 
1017 static ULONG WINAPI OleContainer_AddRef(IOleContainer *iface)
1018 {
1019     HTMLDocument *This = impl_from_IOleContainer(iface);
1020     return htmldoc_addref(This);
1021 }
1022 
1023 static ULONG WINAPI OleContainer_Release(IOleContainer *iface)
1024 {
1025     HTMLDocument *This = impl_from_IOleContainer(iface);
1026     return htmldoc_release(This);
1027 }
1028 
1029 static HRESULT WINAPI OleContainer_ParseDisplayName(IOleContainer *iface, IBindCtx *pbc, LPOLESTR pszDisplayName,
1030         ULONG *pchEaten, IMoniker **ppmkOut)
1031 {
1032     HTMLDocument *This = impl_from_IOleContainer(iface);
1033     FIXME("(%p)->(%p %s %p %p)\n", This, pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut);
1034     return E_NOTIMPL;
1035 }
1036 
1037 static HRESULT WINAPI OleContainer_EnumObjects(IOleContainer *iface, DWORD grfFlags, IEnumUnknown **ppenum)
1038 {
1039     HTMLDocument *This = impl_from_IOleContainer(iface);
1040     EnumUnknown *ret;
1041 
1042     TRACE("(%p)->(%x %p)\n", This, grfFlags, ppenum);
1043 
1044     ret = heap_alloc(sizeof(*ret));
1045     if(!ret)
1046         return E_OUTOFMEMORY;
1047 
1048     ret->IEnumUnknown_iface.lpVtbl = &EnumUnknownVtbl;
1049     ret->ref = 1;
1050 
1051     *ppenum = &ret->IEnumUnknown_iface;
1052     return S_OK;
1053 }
1054 
1055 static HRESULT WINAPI OleContainer_LockContainer(IOleContainer *iface, BOOL fLock)
1056 {
1057     HTMLDocument *This = impl_from_IOleContainer(iface);
1058     FIXME("(%p)->(%x)\n", This, fLock);
1059     return E_NOTIMPL;
1060 }
1061 
1062 static const IOleContainerVtbl OleContainerVtbl = {
1063     OleContainer_QueryInterface,
1064     OleContainer_AddRef,
1065     OleContainer_Release,
1066     OleContainer_ParseDisplayName,
1067     OleContainer_EnumObjects,
1068     OleContainer_LockContainer
1069 };
1070 
1071 static inline HTMLDocumentObj *impl_from_ITargetContainer(ITargetContainer *iface)
1072 {
1073     return CONTAINING_RECORD(iface, HTMLDocumentObj, ITargetContainer_iface);
1074 }
1075 
1076 static HRESULT WINAPI TargetContainer_QueryInterface(ITargetContainer *iface, REFIID riid, void **ppv)
1077 {
1078     HTMLDocumentObj *This = impl_from_ITargetContainer(iface);
1079     return ICustomDoc_QueryInterface(&This->ICustomDoc_iface, riid, ppv);
1080 }
1081 
1082 static ULONG WINAPI TargetContainer_AddRef(ITargetContainer *iface)
1083 {
1084     HTMLDocumentObj *This = impl_from_ITargetContainer(iface);
1085     return ICustomDoc_AddRef(&This->ICustomDoc_iface);
1086 }
1087 
1088 static ULONG WINAPI TargetContainer_Release(ITargetContainer *iface)
1089 {
1090     HTMLDocumentObj *This = impl_from_ITargetContainer(iface);
1091     return ICustomDoc_Release(&This->ICustomDoc_iface);
1092 }
1093 
1094 static HRESULT WINAPI TargetContainer_GetFrameUrl(ITargetContainer *iface, LPWSTR *ppszFrameSrc)
1095 {
1096     HTMLDocumentObj *This = impl_from_ITargetContainer(iface);
1097     FIXME("(%p)->(%p)\n", This, ppszFrameSrc);
1098     return E_NOTIMPL;
1099 }
1100 
1101 static HRESULT WINAPI TargetContainer_GetFramesContainer(ITargetContainer *iface, IOleContainer **ppContainer)
1102 {
1103     HTMLDocumentObj *This = impl_from_ITargetContainer(iface);
1104 
1105     TRACE("(%p)->(%p)\n", This, ppContainer);
1106 
1107     /* NOTE: we should return wrapped interface here */
1108     IOleContainer_AddRef(&This->basedoc.IOleContainer_iface);
1109     *ppContainer = &This->basedoc.IOleContainer_iface;
1110     return S_OK;
1111 }
1112 
1113 static const ITargetContainerVtbl TargetContainerVtbl = {
1114     TargetContainer_QueryInterface,
1115     TargetContainer_AddRef,
1116     TargetContainer_Release,
1117     TargetContainer_GetFrameUrl,
1118     TargetContainer_GetFramesContainer
1119 };
1120 
1121 void TargetContainer_Init(HTMLDocumentObj *This)
1122 {
1123     This->ITargetContainer_iface.lpVtbl = &TargetContainerVtbl;
1124 }
1125 
1126 /**********************************************************
1127  * IObjectSafety implementation
1128  */
1129 
1130 static inline HTMLDocument *impl_from_IObjectSafety(IObjectSafety *iface)
1131 {
1132     return CONTAINING_RECORD(iface, HTMLDocument, IObjectSafety_iface);
1133 }
1134 
1135 static HRESULT WINAPI ObjectSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
1136 {
1137     HTMLDocument *This = impl_from_IObjectSafety(iface);
1138     return htmldoc_query_interface(This, riid, ppv);
1139 }
1140 
1141 static ULONG WINAPI ObjectSafety_AddRef(IObjectSafety *iface)
1142 {
1143     HTMLDocument *This = impl_from_IObjectSafety(iface);
1144     return htmldoc_addref(This);
1145 }
1146 
1147 static ULONG WINAPI ObjectSafety_Release(IObjectSafety *iface)
1148 {
1149     HTMLDocument *This = impl_from_IObjectSafety(iface);
1150     return htmldoc_release(This);
1151 }
1152 
1153 static HRESULT WINAPI ObjectSafety_GetInterfaceSafetyOptions(IObjectSafety *iface,
1154         REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
1155 {
1156     HTMLDocument *This = impl_from_IObjectSafety(iface);
1157     FIXME("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
1158     return E_NOTIMPL;
1159 }
1160 
1161 static HRESULT WINAPI ObjectSafety_SetInterfaceSafetyOptions(IObjectSafety *iface,
1162         REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
1163 {
1164     HTMLDocument *This = impl_from_IObjectSafety(iface);
1165     FIXME("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
1166 
1167     if(IsEqualGUID(&IID_IPersistMoniker, riid) &&
1168             dwOptionSetMask==INTERFACESAFE_FOR_UNTRUSTED_DATA &&
1169             dwEnabledOptions==INTERFACESAFE_FOR_UNTRUSTED_DATA)
1170         return S_OK;
1171 
1172     return E_NOTIMPL;
1173 }
1174 
1175 static const IObjectSafetyVtbl ObjectSafetyVtbl = {
1176     ObjectSafety_QueryInterface,
1177     ObjectSafety_AddRef,
1178     ObjectSafety_Release,
1179     ObjectSafety_GetInterfaceSafetyOptions,
1180     ObjectSafety_SetInterfaceSafetyOptions
1181 };
1182 
1183 void HTMLDocument_LockContainer(HTMLDocumentObj *This, BOOL fLock)
1184 {
1185     IOleContainer *container;
1186     HRESULT hres;
1187 
1188     if(!This->client || This->container_locked == fLock)
1189         return;
1190 
1191     hres = IOleClientSite_GetContainer(This->client, &container);
1192     if(SUCCEEDED(hres)) {
1193         IOleContainer_LockContainer(container, fLock);
1194         This->container_locked = fLock;
1195         IOleContainer_Release(container);
1196     }
1197 }
1198 
1199 void HTMLDocument_OleObj_Init(HTMLDocument *This)
1200 {
1201     This->IOleObject_iface.lpVtbl = &OleObjectVtbl;
1202     This->IOleDocument_iface.lpVtbl = &OleDocumentVtbl;
1203     This->IOleControl_iface.lpVtbl = &OleControlVtbl;
1204     This->IObjectWithSite_iface.lpVtbl = &ObjectWithSiteVtbl;
1205     This->IOleContainer_iface.lpVtbl = &OleContainerVtbl;
1206     This->IObjectSafety_iface.lpVtbl = &ObjectSafetyVtbl;
1207 }
1208