xref: /reactos/dll/win32/ieframe/dochost.c (revision c3cabdbf)
1 /*
2  * Copyright 2005-2006 Jacek Caban for CodeWeavers
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 "ieframe.h"
20 
21 #include "exdispid.h"
22 #include "mshtml.h"
23 #include "perhist.h"
24 #include "initguid.h"
25 
26 #include "wine/debug.h"
27 
28 WINE_DEFAULT_DEBUG_CHANNEL(ieframe);
29 
30 DEFINE_OLEGUID(CGID_DocHostCmdPriv, 0x000214D4L, 0, 0);
31 
32 #define DOCHOST_DOCCANNAVIGATE  0
33 
34 /* Undocumented notification, see mshtml tests */
35 #define CMDID_EXPLORER_UPDATEHISTORY 38
36 
37 static ATOM doc_view_atom = 0;
38 
push_dochost_task(DocHost * This,task_header_t * task,task_proc_t proc,task_destr_t destr,BOOL send)39 void push_dochost_task(DocHost *This, task_header_t *task, task_proc_t proc, task_destr_t destr, BOOL send)
40 {
41     BOOL is_empty;
42 
43     task->proc = proc;
44     task->destr = destr;
45 
46     is_empty = list_empty(&This->task_queue);
47     list_add_tail(&This->task_queue, &task->entry);
48 
49     if(send)
50         SendMessageW(This->frame_hwnd, WM_DOCHOSTTASK, 0, 0);
51     else if(is_empty)
52         PostMessageW(This->frame_hwnd, WM_DOCHOSTTASK, 0, 0);
53 }
54 
process_dochost_tasks(DocHost * This)55 LRESULT process_dochost_tasks(DocHost *This)
56 {
57     task_header_t *task;
58 
59     while(!list_empty(&This->task_queue)) {
60         task = LIST_ENTRY(This->task_queue.next, task_header_t, entry);
61         list_remove(&task->entry);
62 
63         task->proc(This, task);
64         task->destr(task);
65     }
66 
67     return 0;
68 }
69 
abort_dochost_tasks(DocHost * This,task_proc_t proc)70 void abort_dochost_tasks(DocHost *This, task_proc_t proc)
71 {
72     task_header_t *task, *cursor;
73 
74     LIST_FOR_EACH_ENTRY_SAFE(task, cursor, &This->task_queue, task_header_t, entry) {
75         if(proc && proc != task->proc)
76             continue;
77 
78         list_remove(&task->entry);
79         task->destr(task);
80     }
81 }
82 
on_commandstate_change(DocHost * doc_host,LONG command,BOOL enable)83 void on_commandstate_change(DocHost *doc_host, LONG command, BOOL enable)
84 {
85     DISPPARAMS dispparams;
86     VARIANTARG params[2];
87 
88     TRACE("command=%d enable=%d\n", command, enable);
89 
90     dispparams.cArgs = 2;
91     dispparams.cNamedArgs = 0;
92     dispparams.rgdispidNamedArgs = NULL;
93     dispparams.rgvarg = params;
94 
95     V_VT(params) = VT_BOOL;
96     V_BOOL(params) = enable ? VARIANT_TRUE : VARIANT_FALSE;
97 
98     V_VT(params+1) = VT_I4;
99     V_I4(params+1) = command;
100 
101     call_sink(doc_host->cps.wbe2, DISPID_COMMANDSTATECHANGE, &dispparams);
102 
103     doc_host->container_vtbl->on_command_state_change(doc_host, command, enable);
104 }
105 
update_navigation_commands(DocHost * dochost)106 void update_navigation_commands(DocHost *dochost)
107 {
108     unsigned pos = dochost->travellog.loading_pos == -1 ? dochost->travellog.position : dochost->travellog.loading_pos;
109 
110     on_commandstate_change(dochost, CSC_NAVIGATEBACK, pos > 0);
111     on_commandstate_change(dochost, CSC_NAVIGATEFORWARD, pos < dochost->travellog.length);
112 }
113 
notif_complete(DocHost * This,DISPID dispid)114 static void notif_complete(DocHost *This, DISPID dispid)
115 {
116     DISPPARAMS dispparams;
117     VARIANTARG params[2];
118     VARIANT url;
119 
120     dispparams.cArgs = 2;
121     dispparams.cNamedArgs = 0;
122     dispparams.rgdispidNamedArgs = NULL;
123     dispparams.rgvarg = params;
124 
125     V_VT(params) = (VT_BYREF|VT_VARIANT);
126     V_BYREF(params) = &url;
127 
128     V_VT(params+1) = VT_DISPATCH;
129     V_DISPATCH(params+1) = (IDispatch*)This->wb;
130 
131     V_VT(&url) = VT_BSTR;
132     V_BSTR(&url) = SysAllocString(This->url);
133 
134     TRACE("%d >>>\n", dispid);
135     call_sink(This->cps.wbe2, dispid, &dispparams);
136     TRACE("%d <<<\n", dispid);
137 
138     SysFreeString(V_BSTR(&url));
139 }
140 
object_available(DocHost * This)141 static void object_available(DocHost *This)
142 {
143     IHlinkTarget *hlink;
144     HRESULT hres;
145 
146     TRACE("(%p)\n", This);
147 
148     if(!This->document) {
149         WARN("document == NULL\n");
150         return;
151     }
152 
153     hres = IUnknown_QueryInterface(This->document, &IID_IHlinkTarget, (void**)&hlink);
154     if(SUCCEEDED(hres)) {
155         hres = IHlinkTarget_Navigate(hlink, 0, NULL);
156         IHlinkTarget_Release(hlink);
157         if(FAILED(hres))
158             FIXME("Navigate failed\n");
159     }else {
160         IOleObject *ole_object;
161         RECT rect;
162 
163         TRACE("No IHlink iface\n");
164 
165         hres = IUnknown_QueryInterface(This->document, &IID_IOleObject, (void**)&ole_object);
166         if(FAILED(hres)) {
167             FIXME("Could not get IOleObject iface: %08x\n", hres);
168             return;
169         }
170 
171         GetClientRect(This->hwnd, &rect);
172         hres = IOleObject_DoVerb(ole_object, OLEIVERB_SHOW, NULL, &This->IOleClientSite_iface, -1, This->hwnd, &rect);
173         IOleObject_Release(ole_object);
174         if(FAILED(hres))
175             FIXME("DoVerb failed: %08x\n", hres);
176     }
177 }
178 
get_doc_ready_state(DocHost * This,READYSTATE * ret)179 static HRESULT get_doc_ready_state(DocHost *This, READYSTATE *ret)
180 {
181     DISPPARAMS dp = {NULL,NULL,0,0};
182     IDispatch *disp;
183     EXCEPINFO ei;
184     VARIANT var;
185     HRESULT hres;
186 
187     hres = IUnknown_QueryInterface(This->document, &IID_IDispatch, (void**)&disp);
188     if(FAILED(hres))
189         return hres;
190 
191     hres = IDispatch_Invoke(disp, DISPID_READYSTATE, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,
192             &dp, &var, &ei, NULL);
193     IDispatch_Release(disp);
194     if(FAILED(hres)) {
195         WARN("Invoke(DISPID_READYSTATE failed: %08x\n", hres);
196         return hres;
197     }
198 
199     if(V_VT(&var) != VT_I4) {
200         WARN("V_VT(var) = %d\n", V_VT(&var));
201         VariantClear(&var);
202         return E_FAIL;
203     }
204 
205     *ret = V_I4(&var);
206     return S_OK;
207 }
208 
advise_prop_notif(DocHost * This,BOOL set)209 static void advise_prop_notif(DocHost *This, BOOL set)
210 {
211     IConnectionPointContainer *cp_container;
212     IConnectionPoint *cp;
213     HRESULT hres;
214 
215     hres = IUnknown_QueryInterface(This->document, &IID_IConnectionPointContainer, (void**)&cp_container);
216     if(FAILED(hres))
217         return;
218 
219     hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &IID_IPropertyNotifySink, &cp);
220     IConnectionPointContainer_Release(cp_container);
221     if(FAILED(hres))
222         return;
223 
224     if(set)
225         hres = IConnectionPoint_Advise(cp, (IUnknown*)&This->IPropertyNotifySink_iface, &This->prop_notif_cookie);
226     else
227         hres = IConnectionPoint_Unadvise(cp, This->prop_notif_cookie);
228     IConnectionPoint_Release(cp);
229 
230     if(SUCCEEDED(hres))
231         This->is_prop_notif = set;
232 }
233 
set_doc_state(DocHost * This,READYSTATE doc_state)234 void set_doc_state(DocHost *This, READYSTATE doc_state)
235 {
236     This->doc_state = doc_state;
237     if(doc_state > This->ready_state)
238         This->ready_state = doc_state;
239 }
240 
update_ready_state(DocHost * This,READYSTATE ready_state)241 static void update_ready_state(DocHost *This, READYSTATE ready_state)
242 {
243     if(ready_state > READYSTATE_LOADING && This->travellog.loading_pos != -1) {
244         WARN("histupdate not notified\n");
245         This->travellog.position = This->travellog.loading_pos;
246         This->travellog.loading_pos = -1;
247     }
248 
249     if(ready_state > READYSTATE_LOADING && This->doc_state <= READYSTATE_LOADING && !This->browser_service /* FIXME */)
250         notif_complete(This, DISPID_NAVIGATECOMPLETE2);
251 
252     if(ready_state == READYSTATE_COMPLETE && This->doc_state < READYSTATE_COMPLETE) {
253         set_doc_state(This, READYSTATE_COMPLETE);
254         if(!This->browser_service) /* FIXME: Not fully correct */
255             notif_complete(This, DISPID_DOCUMENTCOMPLETE);
256     }else {
257         set_doc_state(This, ready_state);
258     }
259 }
260 
261 typedef struct {
262     task_header_t header;
263     IUnknown *doc;
264     READYSTATE ready_state;
265 } ready_state_task_t;
266 
ready_state_task_destr(task_header_t * _task)267 static void ready_state_task_destr(task_header_t *_task)
268 {
269     ready_state_task_t *task = (ready_state_task_t*)_task;
270 
271     IUnknown_Release(task->doc);
272     heap_free(task);
273 }
274 
ready_state_proc(DocHost * This,task_header_t * _task)275 static void ready_state_proc(DocHost *This, task_header_t *_task)
276 {
277     ready_state_task_t *task = (ready_state_task_t*)_task;
278 
279     if(task->doc == This->document)
280         update_ready_state(This, task->ready_state);
281 }
282 
push_ready_state_task(DocHost * This,READYSTATE ready_state)283 static void push_ready_state_task(DocHost *This, READYSTATE ready_state)
284 {
285     ready_state_task_t *task = heap_alloc(sizeof(ready_state_task_t));
286 
287     IUnknown_AddRef(This->document);
288     task->doc = This->document;
289     task->ready_state = ready_state;
290 
291     push_dochost_task(This, &task->header, ready_state_proc, ready_state_task_destr, FALSE);
292 }
293 
object_available_task_destr(task_header_t * task)294 static void object_available_task_destr(task_header_t *task)
295 {
296     heap_free(task);
297 }
298 
object_available_proc(DocHost * This,task_header_t * task)299 static void object_available_proc(DocHost *This, task_header_t *task)
300 {
301     object_available(This);
302 }
303 
dochost_object_available(DocHost * This,IUnknown * doc)304 HRESULT dochost_object_available(DocHost *This, IUnknown *doc)
305 {
306     READYSTATE ready_state;
307     task_header_t *task;
308     IOleObject *oleobj;
309     HRESULT hres;
310 
311     IUnknown_AddRef(doc);
312     This->document = doc;
313 
314     hres = IUnknown_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj);
315     if(SUCCEEDED(hres)) {
316         CLSID clsid;
317 
318         hres = IOleObject_GetUserClassID(oleobj, &clsid);
319         if(SUCCEEDED(hres))
320             TRACE("Got clsid %s\n",
321                   IsEqualGUID(&clsid, &CLSID_HTMLDocument) ? "CLSID_HTMLDocument" : debugstr_guid(&clsid));
322 
323         hres = IOleObject_SetClientSite(oleobj, &This->IOleClientSite_iface);
324         if(FAILED(hres))
325             FIXME("SetClientSite failed: %08x\n", hres);
326 
327         IOleObject_Release(oleobj);
328     }else {
329         FIXME("Could not get IOleObject iface: %08x\n", hres);
330     }
331 
332     /* FIXME: Call SetAdvise */
333 
334     task = heap_alloc(sizeof(*task));
335     push_dochost_task(This, task, object_available_proc, object_available_task_destr, FALSE);
336 
337     hres = get_doc_ready_state(This, &ready_state);
338     if(SUCCEEDED(hres)) {
339         if(ready_state == READYSTATE_COMPLETE)
340             push_ready_state_task(This, READYSTATE_COMPLETE);
341         if(ready_state != READYSTATE_COMPLETE || This->doc_navigate)
342             advise_prop_notif(This, TRUE);
343     }else if(!This->doc_navigate) {
344         /* If we can't get document's ready state, there is not much we can do.
345          * Assume that document is complete at this point. */
346         push_ready_state_task(This, READYSTATE_COMPLETE);
347     }
348 
349     return S_OK;
350 }
351 
resize_document(DocHost * This,LONG width,LONG height)352 static LRESULT resize_document(DocHost *This, LONG width, LONG height)
353 {
354     RECT rect = {0, 0, width, height};
355 
356     TRACE("(%p)->(%d %d)\n", This, width, height);
357 
358     if(This->view)
359         IOleDocumentView_SetRect(This->view, &rect);
360 
361     return 0;
362 }
363 
doc_view_proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)364 static LRESULT WINAPI doc_view_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
365 {
366     DocHost *This;
367 
368     static const WCHAR wszTHIS[] = {'T','H','I','S',0};
369 
370     if(msg == WM_CREATE) {
371         This = *(DocHost**)lParam;
372         SetPropW(hwnd, wszTHIS, This);
373     }else {
374         This = GetPropW(hwnd, wszTHIS);
375     }
376 
377     switch(msg) {
378     case WM_SIZE:
379         return resize_document(This, LOWORD(lParam), HIWORD(lParam));
380     }
381 
382     return DefWindowProcW(hwnd, msg, wParam, lParam);
383 }
384 
free_travellog_entry(travellog_entry_t * entry)385 static void free_travellog_entry(travellog_entry_t *entry)
386 {
387     if(entry->stream)
388         IStream_Release(entry->stream);
389     heap_free(entry->url);
390 }
391 
get_travellog_stream(DocHost * This)392 static IStream *get_travellog_stream(DocHost *This)
393 {
394     IPersistHistory *persist_history;
395     IStream *stream;
396     HRESULT hres;
397 
398     hres = IUnknown_QueryInterface(This->document, &IID_IPersistHistory, (void**)&persist_history);
399     if(FAILED(hres))
400         return NULL;
401 
402     hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
403     if(SUCCEEDED(hres))
404         hres = IPersistHistory_SaveHistory(persist_history, stream);
405     IPersistHistory_Release(persist_history);
406     if(FAILED(hres)) {
407         IStream_Release(stream);
408         return NULL;
409     }
410 
411     return stream;
412 }
413 
dump_travellog(DocHost * This)414 static void dump_travellog(DocHost *This)
415 {
416     unsigned i;
417 
418     for(i=0; i < This->travellog.length; i++)
419         TRACE("%d: %s %s\n", i, i == This->travellog.position ? "=>" : "  ", debugstr_w(This->travellog.log[i].url));
420     if(i == This->travellog.position)
421         TRACE("%d: =>\n", i);
422 }
423 
update_travellog(DocHost * This)424 static void update_travellog(DocHost *This)
425 {
426     travellog_entry_t *new_entry;
427 
428     static const WCHAR about_schemeW[] = {'a','b','o','u','t',':'};
429 
430     if(This->url && !_wcsnicmp(This->url, about_schemeW, ARRAY_SIZE(about_schemeW))) {
431         TRACE("Skipping about URL\n");
432         return;
433     }
434 
435     if(!This->travellog.log) {
436         This->travellog.log = heap_alloc(4 * sizeof(*This->travellog.log));
437         if(!This->travellog.log)
438             return;
439 
440         This->travellog.size = 4;
441     }else if(This->travellog.size < This->travellog.position+1) {
442         travellog_entry_t *new_travellog;
443 
444         new_travellog = heap_realloc(This->travellog.log, This->travellog.size*2*sizeof(*This->travellog.log));
445         if(!new_travellog)
446             return;
447 
448         This->travellog.log = new_travellog;
449         This->travellog.size *= 2;
450     }
451 
452     if(This->travellog.loading_pos == -1) {
453         /* Clear forward history. */
454         while(This->travellog.length > This->travellog.position)
455             free_travellog_entry(This->travellog.log + --This->travellog.length);
456     }
457 
458     new_entry = This->travellog.log + This->travellog.position;
459 
460     new_entry->url = heap_strdupW(This->url);
461     TRACE("Adding %s at %d\n", debugstr_w(This->url), This->travellog.position);
462     if(!new_entry->url)
463         return;
464 
465     new_entry->stream = get_travellog_stream(This);
466 
467     if(This->travellog.loading_pos == -1) {
468         This->travellog.position++;
469     }else {
470          This->travellog.position = This->travellog.loading_pos;
471          This->travellog.loading_pos = -1;
472     }
473     if(This->travellog.position > This->travellog.length)
474         This->travellog.length = This->travellog.position;
475 
476     dump_travellog(This);
477 }
478 
create_doc_view_hwnd(DocHost * This)479 void create_doc_view_hwnd(DocHost *This)
480 {
481     RECT rect;
482 
483     static const WCHAR wszShell_DocObject_View[] =
484         {'S','h','e','l','l',' ','D','o','c','O','b','j','e','c','t',' ','V','i','e','w',0};
485 
486     if(!doc_view_atom) {
487         static WNDCLASSEXW wndclass = {
488             sizeof(wndclass),
489             CS_PARENTDC,
490             doc_view_proc,
491             0, 0 /* native uses 4*/, NULL, NULL, NULL,
492             (HBRUSH)(COLOR_WINDOW + 1), NULL,
493             wszShell_DocObject_View,
494             NULL
495         };
496 
497         wndclass.hInstance = ieframe_instance;
498 
499         doc_view_atom = RegisterClassExW(&wndclass);
500     }
501 
502     This->container_vtbl->get_docobj_rect(This, &rect);
503     This->hwnd = CreateWindowExW(0, wszShell_DocObject_View,
504          wszShell_DocObject_View,
505          WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP,
506          rect.left, rect.top, rect.right, rect.bottom, This->frame_hwnd,
507          NULL, ieframe_instance, This);
508 }
509 
deactivate_document(DocHost * This)510 void deactivate_document(DocHost *This)
511 {
512     IOleInPlaceObjectWindowless *winobj;
513     IOleObject *oleobj = NULL;
514     IHlinkTarget *hlink = NULL;
515     HRESULT hres;
516 
517     if(!This->document) return;
518 
519     if(This->doc_navigate) {
520         IUnknown_Release(This->doc_navigate);
521         This->doc_navigate = NULL;
522     }
523 
524     if(This->is_prop_notif)
525         advise_prop_notif(This, FALSE);
526 
527     if(This->view)
528         IOleDocumentView_UIActivate(This->view, FALSE);
529 
530     hres = IUnknown_QueryInterface(This->document, &IID_IOleInPlaceObjectWindowless,
531                                    (void**)&winobj);
532     if(SUCCEEDED(hres)) {
533         IOleInPlaceObjectWindowless_InPlaceDeactivate(winobj);
534         IOleInPlaceObjectWindowless_Release(winobj);
535     }
536 
537     if(This->view) {
538         IOleDocumentView_Show(This->view, FALSE);
539         IOleDocumentView_CloseView(This->view, 0);
540         IOleDocumentView_SetInPlaceSite(This->view, NULL);
541         IOleDocumentView_Release(This->view);
542         This->view = NULL;
543     }
544 
545     hres = IUnknown_QueryInterface(This->document, &IID_IOleObject, (void**)&oleobj);
546     if(SUCCEEDED(hres))
547         IOleObject_Close(oleobj, OLECLOSE_NOSAVE);
548 
549     hres = IUnknown_QueryInterface(This->document, &IID_IHlinkTarget, (void**)&hlink);
550     if(SUCCEEDED(hres)) {
551         IHlinkTarget_SetBrowseContext(hlink, NULL);
552         IHlinkTarget_Release(hlink);
553     }
554 
555     if(oleobj) {
556         IOleClientSite *client_site = NULL;
557 
558         IOleObject_GetClientSite(oleobj, &client_site);
559         if(client_site) {
560             if(client_site == &This->IOleClientSite_iface)
561                 IOleObject_SetClientSite(oleobj, NULL);
562             IOleClientSite_Release(client_site);
563         }
564 
565         IOleObject_Release(oleobj);
566     }
567 
568     IUnknown_Release(This->document);
569     This->document = NULL;
570 }
571 
refresh_document(DocHost * This,const VARIANT * level)572 HRESULT refresh_document(DocHost *This, const VARIANT *level)
573 {
574     IOleCommandTarget *cmdtrg;
575     VARIANT vin, vout;
576     HRESULT hres;
577 
578     if(level && (V_VT(level) != VT_I4 || V_I4(level) != REFRESH_NORMAL))
579         FIXME("Unsupported refresh level %s\n", debugstr_variant(level));
580 
581     if(!This->document) {
582         FIXME("no document\n");
583         return E_FAIL;
584     }
585 
586     hres = IUnknown_QueryInterface(This->document, &IID_IOleCommandTarget, (void**)&cmdtrg);
587     if(FAILED(hres))
588         return hres;
589 
590     V_VT(&vin) = VT_EMPTY;
591     V_VT(&vout) = VT_EMPTY;
592     hres = IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_REFRESH, OLECMDEXECOPT_PROMPTUSER, &vin, &vout);
593     IOleCommandTarget_Release(cmdtrg);
594     if(FAILED(hres))
595         return hres;
596 
597     VariantClear(&vout);
598     return S_OK;
599 }
600 
release_dochost_client(DocHost * This)601 void release_dochost_client(DocHost *This)
602 {
603     if(This->hwnd) {
604         DestroyWindow(This->hwnd);
605         This->hwnd = NULL;
606     }
607 
608     if(This->hostui) {
609         IDocHostUIHandler_Release(This->hostui);
610         This->hostui = NULL;
611     }
612 
613     if(This->client_disp) {
614         IDispatch_Release(This->client_disp);
615         This->client_disp = NULL;
616     }
617 
618     if(This->frame) {
619         IOleInPlaceFrame_Release(This->frame);
620         This->frame = NULL;
621     }
622 
623     if(This->olecmd) {
624         IOleCommandTarget_Release(This->olecmd);
625         This->olecmd = NULL;
626     }
627 }
628 
impl_from_IOleCommandTarget(IOleCommandTarget * iface)629 static inline DocHost *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
630 {
631     return CONTAINING_RECORD(iface, DocHost, IOleCommandTarget_iface);
632 }
633 
ClOleCommandTarget_QueryInterface(IOleCommandTarget * iface,REFIID riid,void ** ppv)634 static HRESULT WINAPI ClOleCommandTarget_QueryInterface(IOleCommandTarget *iface,
635         REFIID riid, void **ppv)
636 {
637     DocHost *This = impl_from_IOleCommandTarget(iface);
638     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
639 }
640 
ClOleCommandTarget_AddRef(IOleCommandTarget * iface)641 static ULONG WINAPI ClOleCommandTarget_AddRef(IOleCommandTarget *iface)
642 {
643     DocHost *This = impl_from_IOleCommandTarget(iface);
644     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
645 }
646 
ClOleCommandTarget_Release(IOleCommandTarget * iface)647 static ULONG WINAPI ClOleCommandTarget_Release(IOleCommandTarget *iface)
648 {
649     DocHost *This = impl_from_IOleCommandTarget(iface);
650     return IOleClientSite_Release(&This->IOleClientSite_iface);
651 }
652 
ClOleCommandTarget_QueryStatus(IOleCommandTarget * iface,const GUID * pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT * pCmdText)653 static HRESULT WINAPI ClOleCommandTarget_QueryStatus(IOleCommandTarget *iface,
654         const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
655 {
656     DocHost *This = impl_from_IOleCommandTarget(iface);
657     ULONG i;
658 
659     TRACE("(%p)->(%s %u %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds,
660           pCmdText);
661     for(i=0; prgCmds && i < cCmds; i++)
662         TRACE("unsupported command %u (%x)\n", prgCmds[i].cmdID, prgCmds[i].cmdf);
663 
664     return E_NOTIMPL;
665 }
666 
ClOleCommandTarget_Exec(IOleCommandTarget * iface,const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)667 static HRESULT WINAPI ClOleCommandTarget_Exec(IOleCommandTarget *iface,
668         const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn,
669         VARIANT *pvaOut)
670 {
671     DocHost *This = impl_from_IOleCommandTarget(iface);
672 
673     TRACE("(%p)->(%s %d %d %s %s)\n", This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt,
674             debugstr_variant(pvaIn), debugstr_variant(pvaOut));
675 
676     if(!pguidCmdGroup) {
677         switch(nCmdID) {
678         case OLECMDID_UPDATECOMMANDS:
679             if(!This->olecmd)
680                 return E_NOTIMPL;
681             return IOleCommandTarget_Exec(This->olecmd, pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
682         case OLECMDID_SETDOWNLOADSTATE:
683             if(pvaIn && V_VT(pvaIn) == VT_I4)
684                 This->busy = V_I4(pvaIn) ? VARIANT_TRUE : VARIANT_FALSE;
685             if(This->olecmd)
686                 return IOleCommandTarget_Exec(This->olecmd, pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
687 
688             if(!pvaIn || V_VT(pvaIn) != VT_I4)
689                 return E_INVALIDARG;
690 
691             notify_download_state(This, V_I4(pvaIn));
692             return S_OK;
693         default:
694             TRACE("Unimplemented cmdid %d\n", nCmdID);
695             return E_NOTIMPL;
696         }
697     }
698 
699     if(IsEqualGUID(pguidCmdGroup, &CGID_DocHostCmdPriv)) {
700         switch(nCmdID) {
701         case DOCHOST_DOCCANNAVIGATE:
702             if(!pvaIn || V_VT(pvaIn) != VT_UNKNOWN)
703                 return E_INVALIDARG;
704 
705             if(This->doc_navigate)
706                 IUnknown_Release(This->doc_navigate);
707             IUnknown_AddRef(V_UNKNOWN(pvaIn));
708             This->doc_navigate = V_UNKNOWN(pvaIn);
709             return S_OK;
710 
711         case 1: {
712             IHTMLWindow2 *win2;
713             SAFEARRAY *sa = V_ARRAY(pvaIn);
714             VARIANT status_code, url, htmlwindow;
715             LONG ind;
716             HRESULT hres;
717 
718             if(V_VT(pvaIn) != VT_ARRAY || !sa || (SafeArrayGetDim(sa) != 1))
719                 return E_INVALIDARG;
720 
721             ind = 0;
722             hres = SafeArrayGetElement(sa, &ind, &status_code);
723             if(FAILED(hres) || V_VT(&status_code)!=VT_I4)
724                 return E_INVALIDARG;
725 
726             ind = 1;
727             hres = SafeArrayGetElement(sa, &ind, &url);
728             if(FAILED(hres) || V_VT(&url)!=VT_BSTR)
729                 return E_INVALIDARG;
730 
731             ind = 3;
732             hres = SafeArrayGetElement(sa, &ind, &htmlwindow);
733             if(FAILED(hres) || V_VT(&htmlwindow)!=VT_UNKNOWN || !V_UNKNOWN(&htmlwindow))
734                 return E_INVALIDARG;
735 
736             hres = IUnknown_QueryInterface(V_UNKNOWN(&htmlwindow), &IID_IHTMLWindow2, (void**)&win2);
737             if(FAILED(hres))
738                 return E_INVALIDARG;
739 
740             handle_navigation_error(This, V_I4(&status_code), V_BSTR(&url), win2);
741             IHTMLWindow2_Release(win2);
742             return S_OK;
743         }
744 
745         default:
746             TRACE("unsupported command %d of CGID_DocHostCmdPriv\n", nCmdID);
747             return E_NOTIMPL;
748         }
749     }
750 
751     if(IsEqualGUID(pguidCmdGroup, &CGID_Explorer)) {
752         switch(nCmdID) {
753         case CMDID_EXPLORER_UPDATEHISTORY:
754             update_travellog(This);
755             update_navigation_commands(This);
756             return S_OK;
757 
758         default:
759             TRACE("Unimplemented cmdid %d of CGID_Explorer\n", nCmdID);
760             return E_NOTIMPL;
761         }
762     }
763 
764     if(IsEqualGUID(pguidCmdGroup, &CGID_ShellDocView)) {
765         switch(nCmdID) {
766         default:
767             TRACE("Unimplemented cmdid %d of CGID_ShellDocView\n", nCmdID);
768             return E_NOTIMPL;
769         }
770     }
771 
772     if(IsEqualGUID(&CGID_DocHostCommandHandler, pguidCmdGroup)) {
773         if(!This->olecmd)
774             return E_NOTIMPL;
775         return IOleCommandTarget_Exec(This->olecmd, pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
776     }
777 
778     TRACE("Unimplemented cmdid %d of group %s\n", nCmdID, debugstr_guid(pguidCmdGroup));
779     return E_NOTIMPL;
780 }
781 
782 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
783     ClOleCommandTarget_QueryInterface,
784     ClOleCommandTarget_AddRef,
785     ClOleCommandTarget_Release,
786     ClOleCommandTarget_QueryStatus,
787     ClOleCommandTarget_Exec
788 };
789 
impl_from_IDocHostUIHandler2(IDocHostUIHandler2 * iface)790 static inline DocHost *impl_from_IDocHostUIHandler2(IDocHostUIHandler2 *iface)
791 {
792     return CONTAINING_RECORD(iface, DocHost, IDocHostUIHandler2_iface);
793 }
794 
DocHostUIHandler_QueryInterface(IDocHostUIHandler2 * iface,REFIID riid,void ** ppv)795 static HRESULT WINAPI DocHostUIHandler_QueryInterface(IDocHostUIHandler2 *iface,
796                                                       REFIID riid, void **ppv)
797 {
798     DocHost *This = impl_from_IDocHostUIHandler2(iface);
799     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
800 }
801 
DocHostUIHandler_AddRef(IDocHostUIHandler2 * iface)802 static ULONG WINAPI DocHostUIHandler_AddRef(IDocHostUIHandler2 *iface)
803 {
804     DocHost *This = impl_from_IDocHostUIHandler2(iface);
805     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
806 }
807 
DocHostUIHandler_Release(IDocHostUIHandler2 * iface)808 static ULONG WINAPI DocHostUIHandler_Release(IDocHostUIHandler2 *iface)
809 {
810     DocHost *This = impl_from_IDocHostUIHandler2(iface);
811     return IOleClientSite_Release(&This->IOleClientSite_iface);
812 }
813 
DocHostUIHandler_ShowContextMenu(IDocHostUIHandler2 * iface,DWORD dwID,POINT * ppt,IUnknown * pcmdtReserved,IDispatch * pdispReserved)814 static HRESULT WINAPI DocHostUIHandler_ShowContextMenu(IDocHostUIHandler2 *iface,
815          DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
816 {
817     DocHost *This = impl_from_IDocHostUIHandler2(iface);
818     HRESULT hres;
819 
820     TRACE("(%p)->(%d %p %p %p)\n", This, dwID, ppt, pcmdtReserved, pdispReserved);
821 
822     if(This->hostui) {
823         hres = IDocHostUIHandler_ShowContextMenu(This->hostui, dwID, ppt, pcmdtReserved,
824                                                  pdispReserved);
825         if(hres == S_OK)
826             return S_OK;
827     }
828 
829     FIXME("default action not implemented\n");
830     return E_NOTIMPL;
831 }
832 
DocHostUIHandler_GetHostInfo(IDocHostUIHandler2 * iface,DOCHOSTUIINFO * pInfo)833 static HRESULT WINAPI DocHostUIHandler_GetHostInfo(IDocHostUIHandler2 *iface,
834         DOCHOSTUIINFO *pInfo)
835 {
836     DocHost *This = impl_from_IDocHostUIHandler2(iface);
837     HRESULT hres;
838 
839     TRACE("(%p)->(%p)\n", This, pInfo);
840 
841     if(This->hostui) {
842         hres = IDocHostUIHandler_GetHostInfo(This->hostui, pInfo);
843         if(SUCCEEDED(hres))
844             return hres;
845     }
846 
847     pInfo->dwFlags = DOCHOSTUIFLAG_DISABLE_HELP_MENU | DOCHOSTUIFLAG_OPENNEWWIN
848         | DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8 | DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION
849         | DOCHOSTUIFLAG_IME_ENABLE_RECONVERSION;
850     return S_OK;
851 }
852 
DocHostUIHandler_ShowUI(IDocHostUIHandler2 * iface,DWORD dwID,IOleInPlaceActiveObject * pActiveObject,IOleCommandTarget * pCommandTarget,IOleInPlaceFrame * pFrame,IOleInPlaceUIWindow * pDoc)853 static HRESULT WINAPI DocHostUIHandler_ShowUI(IDocHostUIHandler2 *iface, DWORD dwID,
854         IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget,
855         IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc)
856 {
857     DocHost *This = impl_from_IDocHostUIHandler2(iface);
858     FIXME("(%p)->(%d %p %p %p %p)\n", This, dwID, pActiveObject, pCommandTarget,
859           pFrame, pDoc);
860     return E_NOTIMPL;
861 }
862 
DocHostUIHandler_HideUI(IDocHostUIHandler2 * iface)863 static HRESULT WINAPI DocHostUIHandler_HideUI(IDocHostUIHandler2 *iface)
864 {
865     DocHost *This = impl_from_IDocHostUIHandler2(iface);
866     FIXME("(%p)\n", This);
867     return E_NOTIMPL;
868 }
869 
DocHostUIHandler_UpdateUI(IDocHostUIHandler2 * iface)870 static HRESULT WINAPI DocHostUIHandler_UpdateUI(IDocHostUIHandler2 *iface)
871 {
872     DocHost *This = impl_from_IDocHostUIHandler2(iface);
873 
874     TRACE("(%p)\n", This);
875 
876     if(!This->hostui)
877         return S_FALSE;
878 
879     return IDocHostUIHandler_UpdateUI(This->hostui);
880 }
881 
DocHostUIHandler_EnableModeless(IDocHostUIHandler2 * iface,BOOL fEnable)882 static HRESULT WINAPI DocHostUIHandler_EnableModeless(IDocHostUIHandler2 *iface,
883                                                       BOOL fEnable)
884 {
885     DocHost *This = impl_from_IDocHostUIHandler2(iface);
886     FIXME("(%p)->(%x)\n", This, fEnable);
887     return E_NOTIMPL;
888 }
889 
DocHostUIHandler_OnDocWindowActivate(IDocHostUIHandler2 * iface,BOOL fActivate)890 static HRESULT WINAPI DocHostUIHandler_OnDocWindowActivate(IDocHostUIHandler2 *iface,
891                                                            BOOL fActivate)
892 {
893     DocHost *This = impl_from_IDocHostUIHandler2(iface);
894     FIXME("(%p)->(%x)\n", This, fActivate);
895     return E_NOTIMPL;
896 }
897 
DocHostUIHandler_OnFrameWindowActivate(IDocHostUIHandler2 * iface,BOOL fActivate)898 static HRESULT WINAPI DocHostUIHandler_OnFrameWindowActivate(IDocHostUIHandler2 *iface,
899                                                              BOOL fActivate)
900 {
901     DocHost *This = impl_from_IDocHostUIHandler2(iface);
902     FIXME("(%p)->(%x)\n", This, fActivate);
903     return E_NOTIMPL;
904 }
905 
DocHostUIHandler_ResizeBorder(IDocHostUIHandler2 * iface,LPCRECT prcBorder,IOleInPlaceUIWindow * pUIWindow,BOOL fRameWindow)906 static HRESULT WINAPI DocHostUIHandler_ResizeBorder(IDocHostUIHandler2 *iface,
907         LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
908 {
909     DocHost *This = impl_from_IDocHostUIHandler2(iface);
910     FIXME("(%p)->(%p %p %X)\n", This, prcBorder, pUIWindow, fRameWindow);
911     return E_NOTIMPL;
912 }
913 
DocHostUIHandler_TranslateAccelerator(IDocHostUIHandler2 * iface,LPMSG lpMsg,const GUID * pguidCmdGroup,DWORD nCmdID)914 static HRESULT WINAPI DocHostUIHandler_TranslateAccelerator(IDocHostUIHandler2 *iface,
915         LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
916 {
917     DocHost *This = impl_from_IDocHostUIHandler2(iface);
918     HRESULT hr = S_FALSE;
919     TRACE("(%p)->(%p %p %d)\n", This, lpMsg, pguidCmdGroup, nCmdID);
920 
921     if(This->hostui)
922         hr = IDocHostUIHandler_TranslateAccelerator(This->hostui, lpMsg, pguidCmdGroup, nCmdID);
923 
924     return hr;
925 }
926 
DocHostUIHandler_GetOptionKeyPath(IDocHostUIHandler2 * iface,LPOLESTR * pchKey,DWORD dw)927 static HRESULT WINAPI DocHostUIHandler_GetOptionKeyPath(IDocHostUIHandler2 *iface,
928         LPOLESTR *pchKey, DWORD dw)
929 {
930     DocHost *This = impl_from_IDocHostUIHandler2(iface);
931 
932     TRACE("(%p)->(%p %d)\n", This, pchKey, dw);
933 
934     if(This->hostui)
935         return IDocHostUIHandler_GetOptionKeyPath(This->hostui, pchKey, dw);
936 
937     return S_OK;
938 }
939 
DocHostUIHandler_GetDropTarget(IDocHostUIHandler2 * iface,IDropTarget * pDropTarget,IDropTarget ** ppDropTarget)940 static HRESULT WINAPI DocHostUIHandler_GetDropTarget(IDocHostUIHandler2 *iface,
941         IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
942 {
943     DocHost *This = impl_from_IDocHostUIHandler2(iface);
944     FIXME("(%p)\n", This);
945     return E_NOTIMPL;
946 }
947 
DocHostUIHandler_GetExternal(IDocHostUIHandler2 * iface,IDispatch ** ppDispatch)948 static HRESULT WINAPI DocHostUIHandler_GetExternal(IDocHostUIHandler2 *iface,
949         IDispatch **ppDispatch)
950 {
951     DocHost *This = impl_from_IDocHostUIHandler2(iface);
952 
953     TRACE("(%p)->(%p)\n", This, ppDispatch);
954 
955     if(This->hostui)
956         return IDocHostUIHandler_GetExternal(This->hostui, ppDispatch);
957 
958     if(!This->shell_ui_helper) {
959         HRESULT hres;
960 
961         hres = create_shell_ui_helper(&This->shell_ui_helper);
962         if(FAILED(hres))
963             return hres;
964     }
965 
966     *ppDispatch = (IDispatch*)This->shell_ui_helper;
967     IDispatch_AddRef(*ppDispatch);
968     return S_OK;
969 }
970 
DocHostUIHandler_TranslateUrl(IDocHostUIHandler2 * iface,DWORD dwTranslate,OLECHAR * pchURLIn,OLECHAR ** ppchURLOut)971 static HRESULT WINAPI DocHostUIHandler_TranslateUrl(IDocHostUIHandler2 *iface,
972         DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
973 {
974     DocHost *This = impl_from_IDocHostUIHandler2(iface);
975 
976     TRACE("(%p)->(%d %s %p)\n", This, dwTranslate, debugstr_w(pchURLIn), ppchURLOut);
977 
978     if(This->hostui)
979         return IDocHostUIHandler_TranslateUrl(This->hostui, dwTranslate,
980                                               pchURLIn, ppchURLOut);
981 
982     return S_FALSE;
983 }
984 
DocHostUIHandler_FilterDataObject(IDocHostUIHandler2 * iface,IDataObject * pDO,IDataObject ** ppDORet)985 static HRESULT WINAPI DocHostUIHandler_FilterDataObject(IDocHostUIHandler2 *iface,
986         IDataObject *pDO, IDataObject **ppDORet)
987 {
988     DocHost *This = impl_from_IDocHostUIHandler2(iface);
989     FIXME("(%p)->(%p %p)\n", This, pDO, ppDORet);
990     return E_NOTIMPL;
991 }
992 
DocHostUIHandler_GetOverrideKeyPath(IDocHostUIHandler2 * iface,LPOLESTR * pchKey,DWORD dw)993 static HRESULT WINAPI DocHostUIHandler_GetOverrideKeyPath(IDocHostUIHandler2 *iface,
994         LPOLESTR *pchKey, DWORD dw)
995 {
996     DocHost *This = impl_from_IDocHostUIHandler2(iface);
997     IDocHostUIHandler2 *handler;
998     HRESULT hres;
999 
1000     TRACE("(%p)->(%p %d)\n", This, pchKey, dw);
1001 
1002     if(!This->hostui)
1003         return S_OK;
1004 
1005     hres = IDocHostUIHandler_QueryInterface(This->hostui, &IID_IDocHostUIHandler2,
1006                                             (void**)&handler);
1007     if(SUCCEEDED(hres)) {
1008         hres = IDocHostUIHandler2_GetOverrideKeyPath(handler, pchKey, dw);
1009         IDocHostUIHandler2_Release(handler);
1010         return hres;
1011     }
1012 
1013     return S_OK;
1014 }
1015 
1016 static const IDocHostUIHandler2Vtbl DocHostUIHandler2Vtbl = {
1017     DocHostUIHandler_QueryInterface,
1018     DocHostUIHandler_AddRef,
1019     DocHostUIHandler_Release,
1020     DocHostUIHandler_ShowContextMenu,
1021     DocHostUIHandler_GetHostInfo,
1022     DocHostUIHandler_ShowUI,
1023     DocHostUIHandler_HideUI,
1024     DocHostUIHandler_UpdateUI,
1025     DocHostUIHandler_EnableModeless,
1026     DocHostUIHandler_OnDocWindowActivate,
1027     DocHostUIHandler_OnFrameWindowActivate,
1028     DocHostUIHandler_ResizeBorder,
1029     DocHostUIHandler_TranslateAccelerator,
1030     DocHostUIHandler_GetOptionKeyPath,
1031     DocHostUIHandler_GetDropTarget,
1032     DocHostUIHandler_GetExternal,
1033     DocHostUIHandler_TranslateUrl,
1034     DocHostUIHandler_FilterDataObject,
1035     DocHostUIHandler_GetOverrideKeyPath
1036 };
1037 
impl_from_IPropertyNotifySink(IPropertyNotifySink * iface)1038 static inline DocHost *impl_from_IPropertyNotifySink(IPropertyNotifySink *iface)
1039 {
1040     return CONTAINING_RECORD(iface, DocHost, IPropertyNotifySink_iface);
1041 }
1042 
PropertyNotifySink_QueryInterface(IPropertyNotifySink * iface,REFIID riid,void ** ppv)1043 static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
1044         REFIID riid, void **ppv)
1045 {
1046     DocHost *This = impl_from_IPropertyNotifySink(iface);
1047     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1048 }
1049 
PropertyNotifySink_AddRef(IPropertyNotifySink * iface)1050 static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface)
1051 {
1052     DocHost *This = impl_from_IPropertyNotifySink(iface);
1053     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1054 }
1055 
PropertyNotifySink_Release(IPropertyNotifySink * iface)1056 static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface)
1057 {
1058     DocHost *This = impl_from_IPropertyNotifySink(iface);
1059     return IOleClientSite_Release(&This->IOleClientSite_iface);
1060 }
1061 
PropertyNotifySink_OnChanged(IPropertyNotifySink * iface,DISPID dispID)1062 static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
1063 {
1064     DocHost *This = impl_from_IPropertyNotifySink(iface);
1065 
1066     TRACE("(%p)->(%d)\n", This, dispID);
1067 
1068     switch(dispID) {
1069     case DISPID_READYSTATE: {
1070         READYSTATE ready_state;
1071         HRESULT hres;
1072 
1073         hres = get_doc_ready_state(This, &ready_state);
1074         if(FAILED(hres))
1075             return hres;
1076 
1077         if(ready_state == READYSTATE_COMPLETE && !This->doc_navigate)
1078             advise_prop_notif(This, FALSE);
1079 
1080         update_ready_state(This, ready_state);
1081         break;
1082     }
1083     default:
1084         FIXME("unimplemented dispid %d\n", dispID);
1085         return E_NOTIMPL;
1086     }
1087 
1088     return S_OK;
1089 }
1090 
PropertyNotifySink_OnRequestEdit(IPropertyNotifySink * iface,DISPID dispID)1091 static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
1092 {
1093     DocHost *This = impl_from_IPropertyNotifySink(iface);
1094     FIXME("(%p)->(%d)\n", This, dispID);
1095     return E_NOTIMPL;
1096 }
1097 
1098 static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
1099     PropertyNotifySink_QueryInterface,
1100     PropertyNotifySink_AddRef,
1101     PropertyNotifySink_Release,
1102     PropertyNotifySink_OnChanged,
1103     PropertyNotifySink_OnRequestEdit
1104 };
1105 
DocHost_Init(DocHost * This,IWebBrowser2 * wb,const IDocHostContainerVtbl * container)1106 void DocHost_Init(DocHost *This, IWebBrowser2 *wb, const IDocHostContainerVtbl* container)
1107 {
1108     This->IDocHostUIHandler2_iface.lpVtbl  = &DocHostUIHandler2Vtbl;
1109     This->IOleCommandTarget_iface.lpVtbl   = &OleCommandTargetVtbl;
1110     This->IPropertyNotifySink_iface.lpVtbl = &PropertyNotifySinkVtbl;
1111 
1112     This->wb = wb;
1113     This->container_vtbl = container;
1114 
1115     This->ready_state = READYSTATE_UNINITIALIZED;
1116     list_init(&This->task_queue);
1117 
1118     This->travellog.loading_pos = -1;
1119 
1120     DocHost_ClientSite_Init(This);
1121     DocHost_Frame_Init(This);
1122 
1123     ConnectionPointContainer_Init(&This->cps, (IUnknown*)wb);
1124     IEHTMLWindow_Init(This);
1125     NewWindowManager_Init(This);
1126 }
1127 
DocHost_Release(DocHost * This)1128 void DocHost_Release(DocHost *This)
1129 {
1130     if(This->shell_ui_helper)
1131         IShellUIHelper2_Release(This->shell_ui_helper);
1132 
1133     abort_dochost_tasks(This, NULL);
1134     release_dochost_client(This);
1135     DocHost_ClientSite_Release(This);
1136 
1137     ConnectionPointContainer_Destroy(&This->cps);
1138 
1139     while(This->travellog.length)
1140         free_travellog_entry(This->travellog.log + --This->travellog.length);
1141     heap_free(This->travellog.log);
1142 
1143     heap_free(This->url);
1144 }
1145