xref: /reactos/dll/win32/ieframe/navigate.c (revision 53221834)
1 /*
2  * Copyright 2006-2007 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 #ifdef __REACTOS__
20 #include <wchar.h>
21 #endif
22 
23 #define NONAMELESSUNION
24 
25 #include "ieframe.h"
26 
27 #include "exdispid.h"
28 #include "shellapi.h"
29 #include "winreg.h"
30 #include "shlwapi.h"
31 #include "wininet.h"
32 #include "mshtml.h"
33 #include "perhist.h"
34 #include "resource.h"
35 
36 #include "wine/debug.h"
37 
38 WINE_DEFAULT_DEBUG_CHANNEL(ieframe);
39 
40 static const WCHAR emptyW[] = {0};
41 
42 typedef struct {
43     IBindStatusCallback  IBindStatusCallback_iface;
44     IHttpNegotiate       IHttpNegotiate_iface;
45     IHttpSecurity        IHttpSecurity_iface;
46 
47     LONG ref;
48 
49     DocHost *doc_host;
50     IBinding *binding;
51 
52     BSTR url;
53     HGLOBAL post_data;
54     BSTR headers;
55     ULONG post_data_len;
56 } BindStatusCallback;
57 
58 static void dump_BINDINFO(BINDINFO *bi)
59 {
60     static const char * const BINDINFOF_str[] = {
61         "#0",
62         "BINDINFOF_URLENCODESTGMEDDATA",
63         "BINDINFOF_URLENCODEDEXTRAINFO"
64     };
65 
66     static const char * const BINDVERB_str[] = {
67         "BINDVERB_GET",
68         "BINDVERB_POST",
69         "BINDVERB_PUT",
70         "BINDVERB_CUSTOM"
71     };
72 
73     TRACE("\n"
74             "BINDINFO = {\n"
75             "    %d, %s,\n"
76             "    {%d, %p, %p},\n"
77             "    %s,\n"
78             "    %s,\n"
79             "    %s,\n"
80             "    %d, %08x, %d, %d\n"
81             "    {%d %p %x},\n"
82             "    %s\n"
83             "    %p, %d\n"
84             "}\n",
85 
86             bi->cbSize, debugstr_w(bi->szExtraInfo),
87             bi->stgmedData.tymed, bi->stgmedData.u.hGlobal, bi->stgmedData.pUnkForRelease,
88             bi->grfBindInfoF > BINDINFOF_URLENCODEDEXTRAINFO
89                 ? "unknown" : BINDINFOF_str[bi->grfBindInfoF],
90             bi->dwBindVerb > BINDVERB_CUSTOM
91                 ? "unknown" : BINDVERB_str[bi->dwBindVerb],
92             debugstr_w(bi->szCustomVerb),
93             bi->cbstgmedData, bi->dwOptions, bi->dwOptionsFlags, bi->dwCodePage,
94             bi->securityAttributes.nLength,
95             bi->securityAttributes.lpSecurityDescriptor,
96             bi->securityAttributes.bInheritHandle,
97             debugstr_guid(&bi->iid),
98             bi->pUnk, bi->dwReserved
99             );
100 }
101 
102 static void set_status_text(BindStatusCallback *This, ULONG statuscode, LPCWSTR str)
103 {
104     VARIANTARG arg;
105     DISPPARAMS dispparams = {&arg, NULL, 1, 0};
106     WCHAR fmt[IDS_STATUSFMT_MAXLEN];
107     WCHAR buffer[IDS_STATUSFMT_MAXLEN + INTERNET_MAX_URL_LENGTH];
108 
109     if(!This->doc_host)
110         return;
111 
112     TRACE("(%p, %d, %s)\n", This, statuscode, debugstr_w(str));
113     buffer[0] = 0;
114     if (statuscode && str && *str) {
115         fmt[0] = 0;
116         /* the format string must have one "%s" for the str */
117         LoadStringW(ieframe_instance, IDS_STATUSFMT_FIRST + statuscode, fmt, IDS_STATUSFMT_MAXLEN);
118         swprintf(buffer, fmt, str);
119     }
120 
121     V_VT(&arg) = VT_BSTR;
122     V_BSTR(&arg) = str ? SysAllocString(buffer) : SysAllocString(emptyW);
123     TRACE("=> %s\n", debugstr_w(V_BSTR(&arg)));
124 
125     call_sink(This->doc_host->cps.wbe2, DISPID_STATUSTEXTCHANGE, &dispparams);
126 
127     if(This->doc_host->frame)
128         IOleInPlaceFrame_SetStatusText(This->doc_host->frame, buffer);
129 
130     VariantClear(&arg);
131 
132 }
133 
134 HRESULT set_dochost_url(DocHost *This, const WCHAR *url)
135 {
136     WCHAR *new_url;
137 
138     if(url) {
139         new_url = heap_strdupW(url);
140         if(!new_url)
141             return E_OUTOFMEMORY;
142     }else {
143         new_url = NULL;
144     }
145 
146     heap_free(This->url);
147     This->url = new_url;
148 
149     This->container_vtbl->set_url(This, This->url);
150     return S_OK;
151 }
152 
153 void notify_download_state(DocHost *dochost, BOOL is_downloading)
154 {
155     DISPPARAMS dwl_dp = {NULL};
156     TRACE("(%x)\n", is_downloading);
157     dochost->busy = is_downloading ? VARIANT_TRUE : VARIANT_FALSE;
158     call_sink(dochost->cps.wbe2, is_downloading ? DISPID_DOWNLOADBEGIN : DISPID_DOWNLOADCOMPLETE, &dwl_dp);
159 }
160 
161 static inline BindStatusCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
162 {
163     return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallback_iface);
164 }
165 
166 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
167                                                         REFIID riid, void **ppv)
168 {
169     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
170 
171     if(IsEqualGUID(&IID_IUnknown, riid)) {
172         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
173         *ppv = &This->IBindStatusCallback_iface;
174     }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
175         TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv);
176         *ppv = &This->IBindStatusCallback_iface;
177     }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
178         TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv);
179         *ppv = &This->IHttpNegotiate_iface;
180     }else if(IsEqualGUID(&IID_IWindowForBindingUI, riid)) {
181         TRACE("(%p)->(IID_IWindowForBindingUI %p)\n", This, ppv);
182         *ppv = &This->IHttpSecurity_iface;
183     }else if(IsEqualGUID(&IID_IHttpSecurity, riid)) {
184         TRACE("(%p)->(IID_IHttpSecurity %p)\n", This, ppv);
185         *ppv = &This->IHttpSecurity_iface;
186     }else {
187         *ppv = NULL;
188         WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
189         return E_NOINTERFACE;
190     }
191 
192     IUnknown_AddRef((IUnknown*)*ppv);
193     return S_OK;
194 }
195 
196 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
197 {
198     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
199     LONG ref = InterlockedIncrement(&This->ref);
200 
201     TRACE("(%p) ref=%d\n", This, ref);
202 
203     return ref;
204 }
205 
206 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
207 {
208     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
209     LONG ref = InterlockedDecrement(&This->ref);
210 
211     TRACE("(%p) ref=%d\n", This, ref);
212 
213     if(!ref) {
214         if(This->doc_host)
215             IOleClientSite_Release(&This->doc_host->IOleClientSite_iface);
216         if(This->binding)
217             IBinding_Release(This->binding);
218         if(This->post_data)
219             GlobalFree(This->post_data);
220         SysFreeString(This->headers);
221         SysFreeString(This->url);
222         heap_free(This);
223     }
224 
225     return ref;
226 }
227 
228 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
229        DWORD dwReserved, IBinding *pbind)
230 {
231     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
232 
233     TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
234 
235     This->binding = pbind;
236     IBinding_AddRef(This->binding);
237 
238     return S_OK;
239 }
240 
241 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface,
242        LONG *pnPriority)
243 {
244     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
245     FIXME("(%p)->(%p)\n", This, pnPriority);
246     return E_NOTIMPL;
247 }
248 
249 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface,
250        DWORD reserved)
251 {
252     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
253     FIXME("(%p)->(%d)\n", This, reserved);
254     return E_NOTIMPL;
255 }
256 
257 static DWORD get_http_status_code(IBinding *binding)
258 {
259     IWinInetHttpInfo *http_info;
260     DWORD status, size = sizeof(DWORD);
261     HRESULT hres;
262 
263     hres = IBinding_QueryInterface(binding, &IID_IWinInetHttpInfo, (void**)&http_info);
264     if(FAILED(hres))
265         return HTTP_STATUS_OK;
266 
267     hres = IWinInetHttpInfo_QueryInfo(http_info, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER,
268             &status, &size, NULL, NULL);
269     IWinInetHttpInfo_Release(http_info);
270 
271     if(FAILED(hres))
272         return HTTP_STATUS_OK;
273     return status;
274 }
275 
276 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface,
277         ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
278 {
279     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
280     DWORD status_code;
281 
282     TRACE("(%p)->(%d %d %d %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
283           debugstr_w(szStatusText));
284 
285     switch(ulStatusCode) {
286     case BINDSTATUS_REDIRECTING:
287         return set_dochost_url(This->doc_host, szStatusText);
288     case BINDSTATUS_BEGINDOWNLOADDATA:
289         set_status_text(This, ulStatusCode, szStatusText);
290         status_code = get_http_status_code(This->binding);
291         if(status_code != HTTP_STATUS_OK)
292             handle_navigation_error(This->doc_host, status_code, This->url, NULL);
293         return S_OK;
294 
295     case BINDSTATUS_FINDINGRESOURCE:
296     case BINDSTATUS_ENDDOWNLOADDATA:
297     case BINDSTATUS_SENDINGREQUEST:
298         set_status_text(This, ulStatusCode, szStatusText);
299         return S_OK;
300 
301     case BINDSTATUS_CONNECTING:
302     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
303     case BINDSTATUS_CLASSIDAVAILABLE:
304     case BINDSTATUS_MIMETYPEAVAILABLE:
305     case BINDSTATUS_BEGINSYNCOPERATION:
306     case BINDSTATUS_ENDSYNCOPERATION:
307         return S_OK;
308     default:
309         FIXME("status code %u\n", ulStatusCode);
310     }
311 
312     return S_OK;
313 }
314 
315 void handle_navigation_error(DocHost* doc_host, HRESULT hres, BSTR url, IHTMLWindow2 *win2)
316 {
317     VARIANT var_status_code, var_frame_name, var_url;
318     DISPPARAMS dispparams;
319     VARIANTARG params[5];
320     VARIANT_BOOL cancel = VARIANT_FALSE;
321 
322     dispparams.cArgs = 5;
323     dispparams.cNamedArgs = 0;
324     dispparams.rgdispidNamedArgs = NULL;
325     dispparams.rgvarg = params;
326 
327     V_VT(params) = VT_BOOL|VT_BYREF;
328     V_BOOLREF(params) = &cancel;
329 
330     V_VT(params+1) = VT_VARIANT|VT_BYREF;
331     V_VARIANTREF(params+1) = &var_status_code;
332     V_VT(&var_status_code) = VT_I4;
333     V_I4(&var_status_code) = hres;
334 
335     V_VT(params+2) = VT_VARIANT|VT_BYREF;
336     V_VARIANTREF(params+2) = &var_frame_name;
337     V_VT(&var_frame_name) = VT_BSTR;
338     if(win2) {
339         hres = IHTMLWindow2_get_name(win2, &V_BSTR(&var_frame_name));
340         if(FAILED(hres))
341             V_BSTR(&var_frame_name) = NULL;
342     } else
343         V_BSTR(&var_frame_name) = NULL;
344 
345     V_VT(params+3) = VT_VARIANT|VT_BYREF;
346     V_VARIANTREF(params+3) = &var_url;
347     V_VT(&var_url) = VT_BSTR;
348     V_BSTR(&var_url) = url;
349 
350     V_VT(params+4) = VT_DISPATCH;
351     V_DISPATCH(params+4) = (IDispatch*)doc_host->wb;
352 
353     call_sink(doc_host->cps.wbe2, DISPID_NAVIGATEERROR, &dispparams);
354     SysFreeString(V_BSTR(&var_frame_name));
355 
356     if(!cancel)
357         FIXME("Navigate to error page\n");
358 }
359 
360 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface,
361         HRESULT hresult, LPCWSTR szError)
362 {
363     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
364 
365     TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
366 
367     set_status_text(This, 0, emptyW);
368 
369     if(!This->doc_host)
370         return S_OK;
371 
372     if(!This->doc_host->olecmd)
373         notify_download_state(This->doc_host, FALSE);
374     if(FAILED(hresult))
375         handle_navigation_error(This->doc_host, hresult, This->url, NULL);
376 
377     IOleClientSite_Release(&This->doc_host->IOleClientSite_iface);
378     This->doc_host = NULL;
379 
380     IBinding_Release(This->binding);
381     This->binding = NULL;
382 
383     return S_OK;
384 }
385 
386 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
387         DWORD *grfBINDF, BINDINFO *pbindinfo)
388 {
389     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
390 
391     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
392 
393     *grfBINDF = BINDF_ASYNCHRONOUS;
394 
395     if(This->post_data) {
396         pbindinfo->dwBindVerb = BINDVERB_POST;
397 
398         pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
399         pbindinfo->stgmedData.u.hGlobal = This->post_data;
400         pbindinfo->cbstgmedData = This->post_data_len;
401         pbindinfo->stgmedData.pUnkForRelease = (IUnknown*)&This->IBindStatusCallback_iface;
402         IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
403     }
404 
405     return S_OK;
406 }
407 
408 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
409         DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
410 {
411     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
412     FIXME("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
413     return E_NOTIMPL;
414 }
415 
416 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
417         REFIID riid, IUnknown *punk)
418 {
419     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
420 
421     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
422 
423     return dochost_object_available(This->doc_host, punk);
424 }
425 
426 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
427     BindStatusCallback_QueryInterface,
428     BindStatusCallback_AddRef,
429     BindStatusCallback_Release,
430     BindStatusCallback_OnStartBinding,
431     BindStatusCallback_GetPriority,
432     BindStatusCallback_OnLowResource,
433     BindStatusCallback_OnProgress,
434     BindStatusCallback_OnStopBinding,
435     BindStatusCallback_GetBindInfo,
436     BindStatusCallback_OnDataAvailable,
437     BindStatusCallback_OnObjectAvailable
438 };
439 
440 static inline BindStatusCallback *impl_from_IHttpNegotiate(IHttpNegotiate *iface)
441 {
442     return CONTAINING_RECORD(iface, BindStatusCallback, IHttpNegotiate_iface);
443 }
444 
445 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate *iface,
446                                                    REFIID riid, void **ppv)
447 {
448     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
449     return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
450 }
451 
452 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate *iface)
453 {
454     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
455     return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
456 }
457 
458 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate *iface)
459 {
460     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
461     return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
462 }
463 
464 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate *iface,
465         LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
466 {
467     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
468 
469     TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders),
470           dwReserved, pszAdditionalHeaders);
471 
472     if(This->headers) {
473         int size = (lstrlenW(This->headers)+1)*sizeof(WCHAR);
474         *pszAdditionalHeaders = CoTaskMemAlloc(size);
475         memcpy(*pszAdditionalHeaders, This->headers, size);
476     }
477 
478     return S_OK;
479 }
480 
481 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate *iface,
482         DWORD dwResponseCode, LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders,
483         LPWSTR *pszAdditionalRequestHeaders)
484 {
485     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
486     TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
487           debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
488     return S_OK;
489 }
490 
491 static const IHttpNegotiateVtbl HttpNegotiateVtbl = {
492     HttpNegotiate_QueryInterface,
493     HttpNegotiate_AddRef,
494     HttpNegotiate_Release,
495     HttpNegotiate_BeginningTransaction,
496     HttpNegotiate_OnResponse
497 };
498 
499 static inline BindStatusCallback *impl_from_IHttpSecurity(IHttpSecurity *iface)
500 {
501     return CONTAINING_RECORD(iface, BindStatusCallback, IHttpSecurity_iface);
502 }
503 
504 static HRESULT WINAPI HttpSecurity_QueryInterface(IHttpSecurity *iface, REFIID riid, void **ppv)
505 {
506     BindStatusCallback *This = impl_from_IHttpSecurity(iface);
507     return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
508 }
509 
510 static ULONG WINAPI HttpSecurity_AddRef(IHttpSecurity *iface)
511 {
512     BindStatusCallback *This = impl_from_IHttpSecurity(iface);
513     return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
514 }
515 
516 static ULONG WINAPI HttpSecurity_Release(IHttpSecurity *iface)
517 {
518     BindStatusCallback *This = impl_from_IHttpSecurity(iface);
519     return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
520 }
521 
522 static HRESULT WINAPI HttpSecurity_GetWindow(IHttpSecurity *iface, REFGUID rguidReason, HWND *phwnd)
523 {
524     BindStatusCallback *This = impl_from_IHttpSecurity(iface);
525 
526     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(rguidReason), phwnd);
527 
528     if(!This->doc_host)
529         return E_FAIL;
530 
531     *phwnd = This->doc_host->frame_hwnd;
532     return S_OK;
533 }
534 
535 static HRESULT WINAPI HttpSecurity_OnSecurityProblem(IHttpSecurity *iface, DWORD dwProblem)
536 {
537     BindStatusCallback *This = impl_from_IHttpSecurity(iface);
538     FIXME("(%p)->(%u)\n", This, dwProblem);
539     return S_FALSE;
540 }
541 
542 static const IHttpSecurityVtbl HttpSecurityVtbl = {
543     HttpSecurity_QueryInterface,
544     HttpSecurity_AddRef,
545     HttpSecurity_Release,
546     HttpSecurity_GetWindow,
547     HttpSecurity_OnSecurityProblem
548 };
549 
550 static BindStatusCallback *create_callback(DocHost *doc_host, LPCWSTR url, PBYTE post_data,
551         ULONG post_data_len, LPCWSTR headers)
552 {
553     BindStatusCallback *ret = heap_alloc(sizeof(BindStatusCallback));
554 
555     ret->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
556     ret->IHttpNegotiate_iface.lpVtbl      = &HttpNegotiateVtbl;
557     ret->IHttpSecurity_iface.lpVtbl       = &HttpSecurityVtbl;
558 
559     ret->ref = 1;
560     ret->url = SysAllocString(url);
561     ret->post_data = NULL;
562     ret->post_data_len = post_data_len;
563     ret->headers = headers ? SysAllocString(headers) : NULL;
564 
565     ret->doc_host = doc_host;
566     IOleClientSite_AddRef(&doc_host->IOleClientSite_iface);
567 
568     ret->binding = NULL;
569 
570     if(post_data) {
571         ret->post_data = GlobalAlloc(0, post_data_len);
572         memcpy(ret->post_data, post_data, post_data_len);
573     }
574 
575     return ret;
576 }
577 
578 static void on_before_navigate2(DocHost *This, LPCWSTR url, SAFEARRAY *post_data, LPWSTR headers, VARIANT_BOOL *cancel)
579 {
580     VARIANT var_url, var_flags, var_frame_name, var_post_data, var_post_data2, var_headers;
581     DISPPARAMS dispparams;
582     VARIANTARG params[7];
583     WCHAR file_path[MAX_PATH];
584     DWORD file_path_len = ARRAY_SIZE(file_path);
585 
586     dispparams.cArgs = 7;
587     dispparams.cNamedArgs = 0;
588     dispparams.rgdispidNamedArgs = NULL;
589     dispparams.rgvarg = params;
590 
591     V_VT(params) = VT_BOOL|VT_BYREF;
592     V_BOOLREF(params) = cancel;
593 
594     V_VT(params+1) = (VT_BYREF|VT_VARIANT);
595     V_VARIANTREF(params+1) = &var_headers;
596     V_VT(&var_headers) = VT_BSTR;
597     V_BSTR(&var_headers) = headers;
598 
599     V_VT(params+2) = (VT_BYREF|VT_VARIANT);
600     V_VARIANTREF(params+2) = &var_post_data2;
601     V_VT(&var_post_data2) = (VT_BYREF|VT_VARIANT);
602     V_VARIANTREF(&var_post_data2) = &var_post_data;
603 
604     if(post_data) {
605         V_VT(&var_post_data) = VT_UI1|VT_ARRAY;
606         V_ARRAY(&var_post_data) = post_data;
607     }else {
608         V_VT(&var_post_data) = VT_EMPTY;
609     }
610 
611     V_VT(params+3) = (VT_BYREF|VT_VARIANT);
612     V_VARIANTREF(params+3) = &var_frame_name;
613     V_VT(&var_frame_name) = VT_BSTR;
614     V_BSTR(&var_frame_name) = NULL;
615 
616     V_VT(params+4) = (VT_BYREF|VT_VARIANT);
617     V_VARIANTREF(params+4) = &var_flags;
618     V_VT(&var_flags) = VT_I4;
619     V_I4(&var_flags) = 0;
620 
621     V_VT(params+5) = (VT_BYREF|VT_VARIANT);
622     V_VARIANTREF(params+5) = &var_url;
623     V_VT(&var_url) = VT_BSTR;
624     if(PathCreateFromUrlW(url, file_path, &file_path_len, 0) == S_OK)
625         V_BSTR(&var_url) = SysAllocString(file_path);
626     else
627         V_BSTR(&var_url) = SysAllocString(url);
628 
629     V_VT(params+6) = (VT_DISPATCH);
630     V_DISPATCH(params+6) = (IDispatch*)This->wb;
631 
632     call_sink(This->cps.wbe2, DISPID_BEFORENAVIGATE2, &dispparams);
633 
634     SysFreeString(V_BSTR(&var_url));
635 }
636 
637 /* FIXME: urlmon should handle it */
638 static BOOL try_application_url(LPCWSTR url)
639 {
640     SHELLEXECUTEINFOW exec_info;
641     WCHAR app[64];
642     HKEY hkey;
643     DWORD res, type;
644     HRESULT hres;
645 
646     static const WCHAR wszURLProtocol[] = {'U','R','L',' ','P','r','o','t','o','c','o','l',0};
647 
648     hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, app, ARRAY_SIZE(app), NULL, 0);
649     if(FAILED(hres))
650         return FALSE;
651 
652     res = RegOpenKeyW(HKEY_CLASSES_ROOT, app, &hkey);
653     if(res != ERROR_SUCCESS)
654         return FALSE;
655 
656     res = RegQueryValueExW(hkey, wszURLProtocol, NULL, &type, NULL, NULL);
657     RegCloseKey(hkey);
658     if(res != ERROR_SUCCESS || type != REG_SZ)
659         return FALSE;
660 
661     TRACE("opening application %s\n", debugstr_w(app));
662 
663     memset(&exec_info, 0, sizeof(exec_info));
664     exec_info.cbSize = sizeof(exec_info);
665     exec_info.lpFile = url;
666     exec_info.nShow = SW_SHOW;
667 
668     return ShellExecuteExW(&exec_info);
669 }
670 
671 static HRESULT create_moniker(LPCWSTR url, IMoniker **mon)
672 {
673     WCHAR new_url[INTERNET_MAX_URL_LENGTH];
674     DWORD size;
675     HRESULT hres;
676 
677     if(PathIsURLW(url))
678         return CreateURLMoniker(NULL, url, mon);
679 
680     size = ARRAY_SIZE(new_url);
681     hres = UrlApplySchemeW(url, new_url, &size, URL_APPLY_GUESSSCHEME | URL_APPLY_GUESSFILE | URL_APPLY_DEFAULT);
682     TRACE("was %s got %s\n", debugstr_w(url), debugstr_w(new_url));
683     if(FAILED(hres)) {
684         WARN("UrlApplyScheme failed: %08x\n", hres);
685         return hres;
686     }
687 
688     return CreateURLMoniker(NULL, new_url, mon);
689 }
690 
691 static HRESULT bind_to_object(DocHost *This, IMoniker *mon, LPCWSTR url, IBindCtx *bindctx,
692                               IBindStatusCallback *callback)
693 {
694     IUnknown *unk = NULL;
695     WCHAR *display_name;
696     HRESULT hres;
697 
698     if(mon) {
699         IMoniker_AddRef(mon);
700     }else {
701         hres = create_moniker(url, &mon);
702         if(FAILED(hres))
703             return hres;
704     }
705 
706     hres = IMoniker_GetDisplayName(mon, 0, NULL, &display_name);
707     if(FAILED(hres)) {
708         FIXME("GetDisplayName failed: %08x\n", hres);
709         IMoniker_Release(mon);
710         return hres;
711     }
712 
713     hres = set_dochost_url(This, display_name);
714     CoTaskMemFree(display_name);
715     if(FAILED(hres)) {
716         IMoniker_Release(mon);
717         return hres;
718     }
719 
720     IBindCtx_RegisterObjectParam(bindctx, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM,
721                                  (IUnknown*)&This->IOleClientSite_iface);
722 
723     hres = IMoniker_BindToObject(mon, bindctx, NULL, &IID_IUnknown, (void**)&unk);
724     if(SUCCEEDED(hres)) {
725         hres = S_OK;
726         if(unk)
727             IUnknown_Release(unk);
728     }else if(try_application_url(url)) {
729         hres = S_OK;
730     }else {
731         FIXME("BindToObject failed: %08x\n", hres);
732     }
733 
734     IMoniker_Release(mon);
735     return S_OK;
736 }
737 
738 static void html_window_navigate(DocHost *This, IHTMLPrivateWindow *window, BSTR url, BSTR headers, SAFEARRAY *post_data)
739 {
740     VARIANT headers_var, post_data_var;
741     BSTR empty_str;
742     HRESULT hres;
743 
744     hres = set_dochost_url(This, url);
745     if(FAILED(hres))
746         return;
747 
748     empty_str = SysAllocStringLen(NULL, 0);
749 
750     if(headers) {
751         V_VT(&headers_var) = VT_BSTR;
752         V_BSTR(&headers_var) = headers;
753     }else {
754         V_VT(&headers_var) = VT_EMPTY;
755     }
756 
757     if(post_data) {
758         V_VT(&post_data_var) = VT_UI1|VT_ARRAY;
759         V_ARRAY(&post_data_var) = post_data;
760     }else {
761         V_VT(&post_data_var) = VT_EMPTY;
762     }
763 
764     set_doc_state(This, READYSTATE_LOADING);
765     hres = IHTMLPrivateWindow_SuperNavigate(window, url, empty_str, NULL, NULL, &post_data_var, &headers_var, 0);
766     SysFreeString(empty_str);
767     if(FAILED(hres))
768         WARN("SuprtNavigate failed: %08x\n", hres);
769 }
770 
771 typedef struct {
772     task_header_t header;
773     BSTR url;
774     BSTR headers;
775     SAFEARRAY *post_data;
776     BOOL async_notif;
777 } task_doc_navigate_t;
778 
779 static void doc_navigate_task_destr(task_header_t *t)
780 {
781     task_doc_navigate_t *task = (task_doc_navigate_t*)t;
782 
783     SysFreeString(task->url);
784     SysFreeString(task->headers);
785     if(task->post_data)
786         SafeArrayDestroy(task->post_data);
787     heap_free(task);
788 }
789 
790 static void doc_navigate_proc(DocHost *This, task_header_t *t)
791 {
792     task_doc_navigate_t *task = (task_doc_navigate_t*)t;
793     IHTMLPrivateWindow *priv_window;
794     HRESULT hres;
795 
796     if(!This->doc_navigate) {
797         ERR("Skip nav\n");
798         return;
799     }
800 
801     if(task->async_notif) {
802         VARIANT_BOOL cancel = VARIANT_FALSE;
803         on_before_navigate2(This, task->url, task->post_data, task->headers, &cancel);
804         if(cancel) {
805             TRACE("Navigation canceled\n");
806             return;
807         }
808     }
809 
810     hres = IUnknown_QueryInterface(This->doc_navigate, &IID_IHTMLPrivateWindow, (void**)&priv_window);
811     if(SUCCEEDED(hres)) {
812         html_window_navigate(This, priv_window, task->url, task->headers, task->post_data);
813         IHTMLPrivateWindow_Release(priv_window);
814     }else {
815         WARN("Could not get IHTMLPrivateWindow iface: %08x\n", hres);
816     }
817 }
818 
819 static HRESULT async_doc_navigate(DocHost *This, LPCWSTR url, LPCWSTR headers, PBYTE post_data, ULONG post_data_size,
820         BOOL async_notif)
821 {
822     task_doc_navigate_t *task;
823 
824     TRACE("%s\n", debugstr_w(url));
825 
826     task = heap_alloc_zero(sizeof(*task));
827     if(!task)
828         return E_OUTOFMEMORY;
829 
830     task->url = SysAllocString(url);
831     if(!task->url) {
832         doc_navigate_task_destr(&task->header);
833         return E_OUTOFMEMORY;
834     }
835 
836     if(headers) {
837         task->headers = SysAllocString(headers);
838         if(!task->headers) {
839             doc_navigate_task_destr(&task->header);
840             return E_OUTOFMEMORY;
841         }
842     }
843 
844     if(post_data) {
845         task->post_data = SafeArrayCreateVector(VT_UI1, 0, post_data_size);
846         if(!task->post_data) {
847             doc_navigate_task_destr(&task->header);
848             return E_OUTOFMEMORY;
849         }
850 
851         memcpy(task->post_data->pvData, post_data, post_data_size);
852     }
853 
854     if(!async_notif) {
855         VARIANT_BOOL cancel = VARIANT_FALSE;
856 
857         on_before_navigate2(This, task->url, task->post_data, task->headers, &cancel);
858         if(cancel) {
859             TRACE("Navigation canceled\n");
860             doc_navigate_task_destr(&task->header);
861             return S_OK;
862         }
863     }
864 
865     task->async_notif = async_notif;
866     abort_dochost_tasks(This, doc_navigate_proc);
867     push_dochost_task(This, &task->header, doc_navigate_proc, doc_navigate_task_destr, FALSE);
868     return S_OK;
869 }
870 
871 static HRESULT navigate_bsc(DocHost *This, BindStatusCallback *bsc, IMoniker *mon)
872 {
873     VARIANT_BOOL cancel = VARIANT_FALSE;
874     SAFEARRAY *post_data = NULL;
875     IBindCtx *bindctx;
876     HRESULT hres;
877 
878     set_doc_state(This, READYSTATE_LOADING);
879 
880     if(bsc->post_data) {
881         post_data = SafeArrayCreateVector(VT_UI1, 0, bsc->post_data_len);
882         memcpy(post_data->pvData, post_data, bsc->post_data_len);
883     }
884 
885     on_before_navigate2(This, bsc->url, post_data, bsc->headers, &cancel);
886     if(post_data)
887         SafeArrayDestroy(post_data);
888     if(cancel) {
889         FIXME("Navigation canceled\n");
890         return S_OK;
891     }
892 
893     notify_download_state(This, TRUE);
894     This->busy = VARIANT_FALSE;
895 
896     on_commandstate_change(This, CSC_NAVIGATEBACK, FALSE);
897     on_commandstate_change(This, CSC_NAVIGATEFORWARD, FALSE);
898 
899     if(This->document)
900         deactivate_document(This);
901 
902     CreateAsyncBindCtx(0, &bsc->IBindStatusCallback_iface, 0, &bindctx);
903 
904     if(This->frame)
905         IOleInPlaceFrame_EnableModeless(This->frame, FALSE);
906 
907     hres = bind_to_object(This, mon, bsc->url, bindctx, &bsc->IBindStatusCallback_iface);
908 
909     if(This->frame)
910         IOleInPlaceFrame_EnableModeless(This->frame, TRUE);
911 
912     IBindCtx_Release(bindctx);
913 
914     return hres;
915 }
916 
917 typedef struct {
918     task_header_t header;
919     BindStatusCallback *bsc;
920 } task_navigate_bsc_t;
921 
922 static void navigate_bsc_task_destr(task_header_t *t)
923 {
924     task_navigate_bsc_t *task = (task_navigate_bsc_t*)t;
925 
926     IBindStatusCallback_Release(&task->bsc->IBindStatusCallback_iface);
927     heap_free(task);
928 }
929 
930 static void navigate_bsc_proc(DocHost *This, task_header_t *t)
931 {
932     task_navigate_bsc_t *task = (task_navigate_bsc_t*)t;
933 
934     if(!This->hwnd)
935         create_doc_view_hwnd(This);
936 
937     navigate_bsc(This, task->bsc, NULL);
938 }
939 
940 
941 HRESULT navigate_url(DocHost *This, LPCWSTR url, const VARIANT *Flags,
942                      const VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
943 {
944     SAFEARRAY *post_array = NULL;
945     PBYTE post_data = NULL;
946     ULONG post_data_len = 0;
947     LPWSTR headers = NULL;
948     HRESULT hres = S_OK;
949 
950     TRACE("navigating to %s\n", debugstr_w(url));
951 
952     if((Flags && V_VT(Flags) != VT_EMPTY && V_VT(Flags) != VT_ERROR)
953        || (TargetFrameName && V_VT(TargetFrameName) != VT_EMPTY && V_VT(TargetFrameName) != VT_ERROR))
954         FIXME("Unsupported args (Flags %s; TargetFrameName %s)\n", debugstr_variant(Flags), debugstr_variant(TargetFrameName));
955 
956     if(PostData) {
957         if(V_VT(PostData) & VT_ARRAY)
958             post_array = V_ISBYREF(PostData) ? *V_ARRAYREF(PostData) : V_ARRAY(PostData);
959         else
960             WARN("Invalid post data %s\n", debugstr_variant(PostData));
961     }
962 
963     if(post_array) {
964         LONG elem_max;
965         SafeArrayAccessData(post_array, (void**)&post_data);
966         SafeArrayGetUBound(post_array, 1, &elem_max);
967         post_data_len = (elem_max+1) * SafeArrayGetElemsize(post_array);
968     }
969 
970     if(Headers && V_VT(Headers) == VT_BSTR) {
971         headers = V_BSTR(Headers);
972         TRACE("Headers: %s\n", debugstr_w(headers));
973     }
974 
975     set_doc_state(This, READYSTATE_LOADING);
976     This->ready_state = READYSTATE_LOADING;
977 
978     if(This->doc_navigate) {
979         WCHAR new_url[INTERNET_MAX_URL_LENGTH];
980 
981         if(PathIsURLW(url)) {
982             new_url[0] = 0;
983         }else {
984             DWORD size;
985 
986             size = ARRAY_SIZE(new_url);
987             hres = UrlApplySchemeW(url, new_url, &size,
988                     URL_APPLY_GUESSSCHEME | URL_APPLY_GUESSFILE | URL_APPLY_DEFAULT);
989             if(FAILED(hres)) {
990                 WARN("UrlApplyScheme failed: %08x\n", hres);
991                 new_url[0] = 0;
992             }
993         }
994 
995         hres = async_doc_navigate(This, *new_url ? new_url : url, headers, post_data,
996                 post_data_len, TRUE);
997     }else {
998         task_navigate_bsc_t *task;
999 
1000         task = heap_alloc(sizeof(*task));
1001         task->bsc = create_callback(This, url, post_data, post_data_len, headers);
1002         push_dochost_task(This, &task->header, navigate_bsc_proc, navigate_bsc_task_destr, This->url == NULL);
1003     }
1004 
1005     if(post_data)
1006         SafeArrayUnaccessData(post_array);
1007 
1008     return hres;
1009 }
1010 
1011 static HRESULT navigate_hlink(DocHost *This, IMoniker *mon, IBindCtx *bindctx,
1012                               IBindStatusCallback *callback)
1013 {
1014     IHttpNegotiate *http_negotiate;
1015     BindStatusCallback *bsc;
1016     PBYTE post_data = NULL;
1017     ULONG post_data_len = 0;
1018     LPWSTR headers = NULL, url;
1019     BINDINFO bindinfo;
1020     DWORD bindf = 0;
1021     HRESULT hres;
1022 
1023     TRACE("\n");
1024 
1025     hres = IMoniker_GetDisplayName(mon, 0, NULL, &url);
1026     if(FAILED(hres))
1027         FIXME("GetDisplayName failed: %08x\n", hres);
1028 
1029     hres = IBindStatusCallback_QueryInterface(callback, &IID_IHttpNegotiate,
1030                                               (void**)&http_negotiate);
1031     if(SUCCEEDED(hres)) {
1032         static const WCHAR null_string[] = {0};
1033 
1034         IHttpNegotiate_BeginningTransaction(http_negotiate, null_string, null_string, 0,
1035                                             &headers);
1036         IHttpNegotiate_Release(http_negotiate);
1037     }
1038 
1039     memset(&bindinfo, 0, sizeof(bindinfo));
1040     bindinfo.cbSize = sizeof(bindinfo);
1041 
1042     hres = IBindStatusCallback_GetBindInfo(callback, &bindf, &bindinfo);
1043     dump_BINDINFO(&bindinfo);
1044     if(bindinfo.dwBindVerb == BINDVERB_POST) {
1045         post_data_len = bindinfo.cbstgmedData;
1046         if(post_data_len)
1047             post_data = bindinfo.stgmedData.u.hGlobal;
1048     }
1049 
1050     if(This->doc_navigate) {
1051         hres = async_doc_navigate(This, url, headers, post_data, post_data_len, FALSE);
1052     }else {
1053         bsc = create_callback(This, url, post_data, post_data_len, headers);
1054         hres = navigate_bsc(This, bsc, mon);
1055         IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
1056     }
1057 
1058     CoTaskMemFree(url);
1059     CoTaskMemFree(headers);
1060     ReleaseBindInfo(&bindinfo);
1061 
1062     return hres;
1063 }
1064 
1065 HRESULT go_home(DocHost *This)
1066 {
1067     HKEY hkey;
1068     DWORD res, type, size;
1069     WCHAR wszPageName[MAX_PATH];
1070     static const WCHAR wszAboutBlank[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
1071     static const WCHAR wszStartPage[] = {'S','t','a','r','t',' ','P','a','g','e',0};
1072     static const WCHAR wszSubKey[] = {'S','o','f','t','w','a','r','e','\\',
1073                                       'M','i','c','r','o','s','o','f','t','\\',
1074                                       'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
1075                                       'M','a','i','n',0};
1076 
1077     res = RegOpenKeyW(HKEY_CURRENT_USER, wszSubKey, &hkey);
1078     if (res != ERROR_SUCCESS)
1079         return navigate_url(This, wszAboutBlank, NULL, NULL, NULL, NULL);
1080 
1081     size = sizeof(wszPageName);
1082     res = RegQueryValueExW(hkey, wszStartPage, NULL, &type, (LPBYTE)wszPageName, &size);
1083     RegCloseKey(hkey);
1084     if (res != ERROR_SUCCESS || type != REG_SZ)
1085         return navigate_url(This, wszAboutBlank, NULL, NULL, NULL, NULL);
1086 
1087     return navigate_url(This, wszPageName, NULL, NULL, NULL, NULL);
1088 }
1089 
1090 static HRESULT navigate_history(DocHost *This, unsigned travellog_pos)
1091 {
1092     IPersistHistory *persist_history;
1093     travellog_entry_t *entry;
1094     LARGE_INTEGER li;
1095     HRESULT hres;
1096 
1097     if(!This->doc_navigate) {
1098         FIXME("unsupported doc_navigate FALSE\n");
1099         return E_NOTIMPL;
1100     }
1101 
1102     This->travellog.loading_pos = travellog_pos;
1103     entry = This->travellog.log + This->travellog.loading_pos;
1104 
1105     update_navigation_commands(This);
1106 
1107     if(!entry->stream)
1108         return async_doc_navigate(This, entry->url, NULL, NULL, 0, FALSE);
1109 
1110     hres = IUnknown_QueryInterface(This->document, &IID_IPersistHistory, (void**)&persist_history);
1111     if(FAILED(hres))
1112         return hres;
1113 
1114     li.QuadPart = 0;
1115     IStream_Seek(entry->stream, li, STREAM_SEEK_SET, NULL);
1116 
1117     hres = IPersistHistory_LoadHistory(persist_history, entry->stream, NULL);
1118     IPersistHistory_Release(persist_history);
1119     return hres;
1120 }
1121 
1122 HRESULT go_back(DocHost *This)
1123 {
1124     if(!This->travellog.position) {
1125         WARN("No history available\n");
1126         return E_FAIL;
1127     }
1128 
1129     return navigate_history(This, This->travellog.position-1);
1130 }
1131 
1132 HRESULT go_forward(DocHost *This)
1133 {
1134     if(This->travellog.position >= This->travellog.length) {
1135         WARN("No history available\n");
1136         return E_FAIL;
1137     }
1138 
1139     return navigate_history(This, This->travellog.position+1);
1140 }
1141 
1142 HRESULT get_location_url(DocHost *This, BSTR *ret)
1143 {
1144     FIXME("semi-stub\n");
1145 
1146     *ret = This->url ? SysAllocString(This->url) : SysAllocStringLen(NULL, 0);
1147     if(!*ret)
1148         return E_OUTOFMEMORY;
1149 
1150     return This->url ? S_OK : S_FALSE;
1151 }
1152 
1153 static inline HlinkFrame *impl_from_IHlinkFrame(IHlinkFrame *iface)
1154 {
1155     return CONTAINING_RECORD(iface, HlinkFrame, IHlinkFrame_iface);
1156 }
1157 
1158 static HRESULT WINAPI HlinkFrame_QueryInterface(IHlinkFrame *iface, REFIID riid, void **ppv)
1159 {
1160     HlinkFrame *This = impl_from_IHlinkFrame(iface);
1161     return IUnknown_QueryInterface(This->outer, riid, ppv);
1162 }
1163 
1164 static ULONG WINAPI HlinkFrame_AddRef(IHlinkFrame *iface)
1165 {
1166     HlinkFrame *This = impl_from_IHlinkFrame(iface);
1167     return IUnknown_AddRef(This->outer);
1168 }
1169 
1170 static ULONG WINAPI HlinkFrame_Release(IHlinkFrame *iface)
1171 {
1172     HlinkFrame *This = impl_from_IHlinkFrame(iface);
1173     return IUnknown_Release(This->outer);
1174 }
1175 
1176 static HRESULT WINAPI HlinkFrame_SetBrowseContext(IHlinkFrame *iface,
1177                                                   IHlinkBrowseContext *pihlbc)
1178 {
1179     HlinkFrame *This = impl_from_IHlinkFrame(iface);
1180     FIXME("(%p)->(%p)\n", This, pihlbc);
1181     return E_NOTIMPL;
1182 }
1183 
1184 static HRESULT WINAPI HlinkFrame_GetBrowseContext(IHlinkFrame *iface,
1185                                                   IHlinkBrowseContext **ppihlbc)
1186 {
1187     HlinkFrame *This = impl_from_IHlinkFrame(iface);
1188     FIXME("(%p)->(%p)\n", This, ppihlbc);
1189     return E_NOTIMPL;
1190 }
1191 
1192 static HRESULT WINAPI HlinkFrame_Navigate(IHlinkFrame *iface, DWORD grfHLNF, LPBC pbc,
1193                                           IBindStatusCallback *pibsc, IHlink *pihlNavigate)
1194 {
1195     HlinkFrame *This = impl_from_IHlinkFrame(iface);
1196     IMoniker *mon;
1197     LPWSTR location = NULL;
1198 
1199     TRACE("(%p)->(%08x %p %p %p)\n", This, grfHLNF, pbc, pibsc, pihlNavigate);
1200 
1201     if(grfHLNF)
1202         FIXME("unsupported grfHLNF=%08x\n", grfHLNF);
1203 
1204     /* Windows calls GetTargetFrameName here. */
1205 
1206     IHlink_GetMonikerReference(pihlNavigate, 1, &mon, &location);
1207 
1208     if(location) {
1209         FIXME("location = %s\n", debugstr_w(location));
1210         CoTaskMemFree(location);
1211     }
1212 
1213     /* Windows calls GetHlinkSite here */
1214 
1215     if(grfHLNF & HLNF_OPENINNEWWINDOW) {
1216         FIXME("Not supported HLNF_OPENINNEWWINDOW\n");
1217         return E_NOTIMPL;
1218     }
1219 
1220     return navigate_hlink(This->doc_host, mon, pbc, pibsc);
1221 }
1222 
1223 static HRESULT WINAPI HlinkFrame_OnNavigate(IHlinkFrame *iface, DWORD grfHLNF,
1224         IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, DWORD dwreserved)
1225 {
1226     HlinkFrame *This = impl_from_IHlinkFrame(iface);
1227     FIXME("(%p)->(%08x %p %s %s %d)\n", This, grfHLNF, pimkTarget, debugstr_w(pwzLocation),
1228           debugstr_w(pwzFriendlyName), dwreserved);
1229     return E_NOTIMPL;
1230 }
1231 
1232 static HRESULT WINAPI HlinkFrame_UpdateHlink(IHlinkFrame *iface, ULONG uHLID,
1233         IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName)
1234 {
1235     HlinkFrame *This = impl_from_IHlinkFrame(iface);
1236     FIXME("(%p)->(%u %p %s %s)\n", This, uHLID, pimkTarget, debugstr_w(pwzLocation),
1237           debugstr_w(pwzFriendlyName));
1238     return E_NOTIMPL;
1239 }
1240 
1241 static const IHlinkFrameVtbl HlinkFrameVtbl = {
1242     HlinkFrame_QueryInterface,
1243     HlinkFrame_AddRef,
1244     HlinkFrame_Release,
1245     HlinkFrame_SetBrowseContext,
1246     HlinkFrame_GetBrowseContext,
1247     HlinkFrame_Navigate,
1248     HlinkFrame_OnNavigate,
1249     HlinkFrame_UpdateHlink
1250 };
1251 
1252 static inline HlinkFrame *impl_from_ITargetFrame(ITargetFrame *iface)
1253 {
1254     return CONTAINING_RECORD(iface, HlinkFrame, ITargetFrame_iface);
1255 }
1256 
1257 static HRESULT WINAPI TargetFrame_QueryInterface(ITargetFrame *iface, REFIID riid, void **ppv)
1258 {
1259     HlinkFrame *This = impl_from_ITargetFrame(iface);
1260     return IUnknown_QueryInterface(This->outer, riid, ppv);
1261 }
1262 
1263 static ULONG WINAPI TargetFrame_AddRef(ITargetFrame *iface)
1264 {
1265     HlinkFrame *This = impl_from_ITargetFrame(iface);
1266     return IUnknown_AddRef(This->outer);
1267 }
1268 
1269 static ULONG WINAPI TargetFrame_Release(ITargetFrame *iface)
1270 {
1271     HlinkFrame *This = impl_from_ITargetFrame(iface);
1272     return IUnknown_Release(This->outer);
1273 }
1274 
1275 static HRESULT WINAPI TargetFrame_SetFrameName(ITargetFrame *iface, LPCWSTR pszFrameName)
1276 {
1277     HlinkFrame *This = impl_from_ITargetFrame(iface);
1278     FIXME("(%p)->(%s)\n", This, debugstr_w(pszFrameName));
1279     return E_NOTIMPL;
1280 }
1281 
1282 static HRESULT WINAPI TargetFrame_GetFrameName(ITargetFrame *iface, LPWSTR *ppszFrameName)
1283 {
1284     HlinkFrame *This = impl_from_ITargetFrame(iface);
1285     FIXME("(%p)->(%p)\n", This, ppszFrameName);
1286     return E_NOTIMPL;
1287 }
1288 
1289 static HRESULT WINAPI TargetFrame_GetParentFrame(ITargetFrame *iface, IUnknown **ppunkParent)
1290 {
1291     HlinkFrame *This = impl_from_ITargetFrame(iface);
1292     FIXME("(%p)->(%p)\n", This, ppunkParent);
1293     return E_NOTIMPL;
1294 }
1295 
1296 static HRESULT WINAPI TargetFrame_FindFrame(ITargetFrame *iface, LPCWSTR pszTargetName,
1297         IUnknown *ppunkContextFrame, DWORD dwFlags, IUnknown **ppunkTargetFrame)
1298 {
1299     HlinkFrame *This = impl_from_ITargetFrame(iface);
1300     FIXME("(%p)->(%s %p %x %p)\n", This, debugstr_w(pszTargetName),
1301             ppunkContextFrame, dwFlags, ppunkTargetFrame);
1302     return E_NOTIMPL;
1303 }
1304 
1305 static HRESULT WINAPI TargetFrame_SetFrameSrc(ITargetFrame *iface, LPCWSTR pszFrameSrc)
1306 {
1307     HlinkFrame *This = impl_from_ITargetFrame(iface);
1308     FIXME("(%p)->(%s)\n", This, debugstr_w(pszFrameSrc));
1309     return E_NOTIMPL;
1310 }
1311 
1312 static HRESULT WINAPI TargetFrame_GetFrameSrc(ITargetFrame *iface, LPWSTR *ppszFrameSrc)
1313 {
1314     HlinkFrame *This = impl_from_ITargetFrame(iface);
1315     FIXME("(%p)->(%p)\n", This, ppszFrameSrc);
1316     return E_NOTIMPL;
1317 }
1318 
1319 static HRESULT WINAPI TargetFrame_GetFramesContainer(ITargetFrame *iface, IOleContainer **ppContainer)
1320 {
1321     HlinkFrame *This = impl_from_ITargetFrame(iface);
1322     FIXME("(%p)->(%p)\n", This, ppContainer);
1323     return E_NOTIMPL;
1324 }
1325 
1326 static HRESULT WINAPI TargetFrame_SetFrameOptions(ITargetFrame *iface, DWORD dwFlags)
1327 {
1328     HlinkFrame *This = impl_from_ITargetFrame(iface);
1329     FIXME("(%p)->(%x)\n", This, dwFlags);
1330     return E_NOTIMPL;
1331 }
1332 
1333 static HRESULT WINAPI TargetFrame_GetFrameOptions(ITargetFrame *iface, DWORD *pdwFlags)
1334 {
1335     HlinkFrame *This = impl_from_ITargetFrame(iface);
1336     FIXME("(%p)->(%p)\n", This, pdwFlags);
1337     return E_NOTIMPL;
1338 }
1339 
1340 static HRESULT WINAPI TargetFrame_SetFrameMargins(ITargetFrame *iface, DWORD dwWidth, DWORD dwHeight)
1341 {
1342     HlinkFrame *This = impl_from_ITargetFrame(iface);
1343     FIXME("(%p)->(%d %d)\n", This, dwWidth, dwHeight);
1344     return E_NOTIMPL;
1345 }
1346 
1347 static HRESULT WINAPI TargetFrame_GetFrameMargins(ITargetFrame *iface, DWORD *pdwWidth, DWORD *pdwHeight)
1348 {
1349     HlinkFrame *This = impl_from_ITargetFrame(iface);
1350     FIXME("(%p)->(%p %p)\n", This, pdwWidth, pdwHeight);
1351     return E_NOTIMPL;
1352 }
1353 
1354 static HRESULT WINAPI TargetFrame_RemoteNavigate(ITargetFrame *iface, ULONG cLength, ULONG *pulData)
1355 {
1356     HlinkFrame *This = impl_from_ITargetFrame(iface);
1357     FIXME("(%p)->(%u %p)\n", This, cLength, pulData);
1358     return E_NOTIMPL;
1359 }
1360 
1361 static HRESULT WINAPI TargetFrame_OnChildFrameActivate(ITargetFrame *iface, IUnknown *pUnkChildFrame)
1362 {
1363     HlinkFrame *This = impl_from_ITargetFrame(iface);
1364     FIXME("(%p)->(%p)\n", This, pUnkChildFrame);
1365     return E_NOTIMPL;
1366 }
1367 
1368 static HRESULT WINAPI TargetFrame_OnChildFrameDeactivate(ITargetFrame *iface, IUnknown *pUnkChildFrame)
1369 {
1370     HlinkFrame *This = impl_from_ITargetFrame(iface);
1371     FIXME("(%p)->(%p)\n", This, pUnkChildFrame);
1372     return E_NOTIMPL;
1373 }
1374 
1375 static const ITargetFrameVtbl TargetFrameVtbl = {
1376     TargetFrame_QueryInterface,
1377     TargetFrame_AddRef,
1378     TargetFrame_Release,
1379     TargetFrame_SetFrameName,
1380     TargetFrame_GetFrameName,
1381     TargetFrame_GetParentFrame,
1382     TargetFrame_FindFrame,
1383     TargetFrame_SetFrameSrc,
1384     TargetFrame_GetFrameSrc,
1385     TargetFrame_GetFramesContainer,
1386     TargetFrame_SetFrameOptions,
1387     TargetFrame_GetFrameOptions,
1388     TargetFrame_SetFrameMargins,
1389     TargetFrame_GetFrameMargins,
1390     TargetFrame_RemoteNavigate,
1391     TargetFrame_OnChildFrameActivate,
1392     TargetFrame_OnChildFrameDeactivate
1393 };
1394 
1395 static inline HlinkFrame *impl_from_ITargetFrame2(ITargetFrame2 *iface)
1396 {
1397     return CONTAINING_RECORD(iface, HlinkFrame, ITargetFrame2_iface);
1398 }
1399 
1400 static HRESULT WINAPI TargetFrame2_QueryInterface(ITargetFrame2 *iface, REFIID riid, void **ppv)
1401 {
1402     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1403     return IUnknown_QueryInterface(This->outer, riid, ppv);
1404 }
1405 
1406 static ULONG WINAPI TargetFrame2_AddRef(ITargetFrame2 *iface)
1407 {
1408     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1409     return IUnknown_AddRef(This->outer);
1410 }
1411 
1412 static ULONG WINAPI TargetFrame2_Release(ITargetFrame2 *iface)
1413 {
1414     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1415     return IUnknown_Release(This->outer);
1416 }
1417 
1418 static HRESULT WINAPI TargetFrame2_SetFrameName(ITargetFrame2 *iface, LPCWSTR pszFrameName)
1419 {
1420     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1421     FIXME("(%p)->(%s)\n", This, debugstr_w(pszFrameName));
1422     return E_NOTIMPL;
1423 }
1424 
1425 static HRESULT WINAPI TargetFrame2_GetFrameName(ITargetFrame2 *iface, LPWSTR *ppszFrameName)
1426 {
1427     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1428     FIXME("(%p)->(%p)\n", This, ppszFrameName);
1429     return E_NOTIMPL;
1430 }
1431 
1432 static HRESULT WINAPI TargetFrame2_GetParentFrame(ITargetFrame2 *iface, IUnknown **ppunkParent)
1433 {
1434     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1435     FIXME("(%p)->(%p)\n", This, ppunkParent);
1436     return E_NOTIMPL;
1437 }
1438 
1439 static HRESULT WINAPI TargetFrame2_SetFrameSrc(ITargetFrame2 *iface, LPCWSTR pszFrameSrc)
1440 {
1441     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1442     FIXME("(%p)->(%s)\n", This, debugstr_w(pszFrameSrc));
1443     return E_NOTIMPL;
1444 }
1445 
1446 static HRESULT WINAPI TargetFrame2_GetFrameSrc(ITargetFrame2 *iface, LPWSTR *ppszFrameSrc)
1447 {
1448     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1449     FIXME("(%p)->()\n", This);
1450     return E_NOTIMPL;
1451 }
1452 
1453 static HRESULT WINAPI TargetFrame2_GetFramesContainer(ITargetFrame2 *iface, IOleContainer **ppContainer)
1454 {
1455     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1456     FIXME("(%p)->(%p)\n", This, ppContainer);
1457     return E_NOTIMPL;
1458 }
1459 
1460 static HRESULT WINAPI TargetFrame2_SetFrameOptions(ITargetFrame2 *iface, DWORD dwFlags)
1461 {
1462     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1463     FIXME("(%p)->(%x)\n", This, dwFlags);
1464     return E_NOTIMPL;
1465 }
1466 
1467 static HRESULT WINAPI TargetFrame2_GetFrameOptions(ITargetFrame2 *iface, DWORD *pdwFlags)
1468 {
1469     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1470     FIXME("(%p)->(%p)\n", This, pdwFlags);
1471     return E_NOTIMPL;
1472 }
1473 
1474 static HRESULT WINAPI TargetFrame2_SetFrameMargins(ITargetFrame2 *iface, DWORD dwWidth, DWORD dwHeight)
1475 {
1476     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1477     FIXME("(%p)->(%d %d)\n", This, dwWidth, dwHeight);
1478     return E_NOTIMPL;
1479 }
1480 
1481 static HRESULT WINAPI TargetFrame2_GetFrameMargins(ITargetFrame2 *iface, DWORD *pdwWidth, DWORD *pdwHeight)
1482 {
1483     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1484     FIXME("(%p)->(%p %p)\n", This, pdwWidth, pdwHeight);
1485     return E_NOTIMPL;
1486 }
1487 
1488 static HRESULT WINAPI TargetFrame2_FindFrame(ITargetFrame2 *iface, LPCWSTR pszTargetName, DWORD dwFlags, IUnknown **ppunkTargetFrame)
1489 {
1490     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1491     FIXME("(%p)->(%s %x %p)\n", This, debugstr_w(pszTargetName), dwFlags, ppunkTargetFrame);
1492     return E_NOTIMPL;
1493 }
1494 
1495 static HRESULT WINAPI TargetFrame2_GetTargetAlias(ITargetFrame2 *iface, LPCWSTR pszTargetName, LPWSTR *ppszTargetAlias)
1496 {
1497     HlinkFrame *This = impl_from_ITargetFrame2(iface);
1498     FIXME("(%p)->(%s %p)\n", This, debugstr_w(pszTargetName), ppszTargetAlias);
1499     return E_NOTIMPL;
1500 }
1501 
1502 static const ITargetFrame2Vtbl TargetFrame2Vtbl = {
1503     TargetFrame2_QueryInterface,
1504     TargetFrame2_AddRef,
1505     TargetFrame2_Release,
1506     TargetFrame2_SetFrameName,
1507     TargetFrame2_GetFrameName,
1508     TargetFrame2_GetParentFrame,
1509     TargetFrame2_SetFrameSrc,
1510     TargetFrame2_GetFrameSrc,
1511     TargetFrame2_GetFramesContainer,
1512     TargetFrame2_SetFrameOptions,
1513     TargetFrame2_GetFrameOptions,
1514     TargetFrame2_SetFrameMargins,
1515     TargetFrame2_GetFrameMargins,
1516     TargetFrame2_FindFrame,
1517     TargetFrame2_GetTargetAlias
1518 };
1519 
1520 static inline HlinkFrame *impl_from_ITargetFramePriv2(ITargetFramePriv2 *iface)
1521 {
1522     return CONTAINING_RECORD(iface, HlinkFrame, ITargetFramePriv2_iface);
1523 }
1524 
1525 static HRESULT WINAPI TargetFramePriv2_QueryInterface(ITargetFramePriv2 *iface, REFIID riid, void **ppv)
1526 {
1527     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1528     return IUnknown_QueryInterface(This->outer, riid, ppv);
1529 }
1530 
1531 static ULONG WINAPI TargetFramePriv2_AddRef(ITargetFramePriv2 *iface)
1532 {
1533     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1534     return IUnknown_AddRef(This->outer);
1535 }
1536 
1537 static ULONG WINAPI TargetFramePriv2_Release(ITargetFramePriv2 *iface)
1538 {
1539     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1540     return IUnknown_Release(This->outer);
1541 }
1542 
1543 static HRESULT WINAPI TargetFramePriv2_FindFrameDownwards(ITargetFramePriv2 *iface,
1544         LPCWSTR pszTargetName, DWORD dwFlags, IUnknown **ppunkTargetFrame)
1545 {
1546     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1547     FIXME("(%p)->(%s %x %p)\n", This, debugstr_w(pszTargetName), dwFlags, ppunkTargetFrame);
1548     return E_NOTIMPL;
1549 }
1550 
1551 static HRESULT WINAPI TargetFramePriv2_FindFrameInContext(ITargetFramePriv2 *iface,
1552         LPCWSTR pszTargetName, IUnknown *punkContextFrame, DWORD dwFlags, IUnknown **ppunkTargetFrame)
1553 {
1554     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1555     FIXME("(%p)->(%s %p %x %p)\n", This, debugstr_w(pszTargetName), punkContextFrame, dwFlags, ppunkTargetFrame);
1556     return E_NOTIMPL;
1557 }
1558 
1559 static HRESULT WINAPI TargetFramePriv2_OnChildFrameActivate(ITargetFramePriv2 *iface, IUnknown *pUnkChildFrame)
1560 {
1561     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1562     FIXME("(%p)->(%p)\n", This, pUnkChildFrame);
1563     return E_NOTIMPL;
1564 }
1565 
1566 static HRESULT WINAPI TargetFramePriv2_OnChildFrameDeactivate(ITargetFramePriv2 *iface, IUnknown *pUnkChildFrame)
1567 {
1568     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1569     FIXME("(%p)->(%p)\n", This, pUnkChildFrame);
1570     return E_NOTIMPL;
1571 }
1572 
1573 static HRESULT WINAPI TargetFramePriv2_NavigateHack(ITargetFramePriv2 *iface, DWORD grfHLNF, LPBC pbc,
1574         IBindStatusCallback *pibsc, LPCWSTR pszTargetName, LPCWSTR pszUrl, LPCWSTR pszLocation)
1575 {
1576     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1577     FIXME("(%p)->(%x %p %p %s %s %s)\n", This, grfHLNF, pbc, pibsc, debugstr_w(pszTargetName),
1578           debugstr_w(pszUrl), debugstr_w(pszLocation));
1579     return E_NOTIMPL;
1580 }
1581 
1582 static HRESULT WINAPI TargetFramePriv2_FindBrowserByIndex(ITargetFramePriv2 *iface, DWORD dwID, IUnknown **ppunkBrowser)
1583 {
1584     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1585     FIXME("(%p)->(%d %p)\n", This, dwID, ppunkBrowser);
1586     return E_NOTIMPL;
1587 }
1588 
1589 static HRESULT WINAPI TargetFramePriv2_AggregatedNavigation2(ITargetFramePriv2 *iface, DWORD grfHLNF, LPBC pbc,
1590         IBindStatusCallback *pibsc, LPCWSTR pszTargetName, IUri *pUri, LPCWSTR pszLocation)
1591 {
1592     HlinkFrame *This = impl_from_ITargetFramePriv2(iface);
1593     IMoniker *mon;
1594     HRESULT hres;
1595 
1596     TRACE("(%p)->(%x %p %p %s %p %s)\n", This, grfHLNF, pbc, pibsc, debugstr_w(pszTargetName),
1597           pUri, debugstr_w(pszLocation));
1598 
1599     /*
1600      * NOTE: This is an undocumented function. It seems to be working the way it's implemented,
1601      * but I couldn't get its tests working. It's used by mshtml to load content in a new
1602      * instance of browser.
1603      */
1604 
1605     hres = CreateURLMonikerEx2(NULL, pUri, &mon, 0);
1606     if(FAILED(hres))
1607         return hres;
1608 
1609     hres = navigate_hlink(This->doc_host, mon, pbc, pibsc);
1610     IMoniker_Release(mon);
1611     return hres;
1612 }
1613 
1614 static const ITargetFramePriv2Vtbl TargetFramePriv2Vtbl = {
1615     TargetFramePriv2_QueryInterface,
1616     TargetFramePriv2_AddRef,
1617     TargetFramePriv2_Release,
1618     TargetFramePriv2_FindFrameDownwards,
1619     TargetFramePriv2_FindFrameInContext,
1620     TargetFramePriv2_OnChildFrameActivate,
1621     TargetFramePriv2_OnChildFrameDeactivate,
1622     TargetFramePriv2_NavigateHack,
1623     TargetFramePriv2_FindBrowserByIndex,
1624     TargetFramePriv2_AggregatedNavigation2
1625 };
1626 
1627 static inline HlinkFrame *impl_from_IWebBrowserPriv2IE9(IWebBrowserPriv2IE9 *iface)
1628 {
1629     return CONTAINING_RECORD(iface, HlinkFrame, IWebBrowserPriv2IE9_iface);
1630 }
1631 
1632 static HRESULT WINAPI WebBrowserPriv2IE9_QueryInterface(IWebBrowserPriv2IE9 *iface, REFIID riid, void **ppv)
1633 {
1634     HlinkFrame *This = impl_from_IWebBrowserPriv2IE9(iface);
1635     return IUnknown_QueryInterface(This->outer, riid, ppv);
1636 }
1637 
1638 static ULONG WINAPI WebBrowserPriv2IE9_AddRef(IWebBrowserPriv2IE9 *iface)
1639 {
1640     HlinkFrame *This = impl_from_IWebBrowserPriv2IE9(iface);
1641     return IUnknown_AddRef(This->outer);
1642 }
1643 
1644 static ULONG WINAPI WebBrowserPriv2IE9_Release(IWebBrowserPriv2IE9 *iface)
1645 {
1646     HlinkFrame *This = impl_from_IWebBrowserPriv2IE9(iface);
1647     return IUnknown_Release(This->outer);
1648 }
1649 
1650 static HRESULT WINAPI WebBrowserPriv2IE9_NavigateWithBindCtx2(IWebBrowserPriv2IE9 *iface, IUri *uri, VARIANT *flags,
1651         VARIANT *target_frame, VARIANT *post_data, VARIANT *headers, IBindCtx *bind_ctx, LPOLESTR url_fragment, DWORD unused)
1652 {
1653     HlinkFrame *This = impl_from_IWebBrowserPriv2IE9(iface);
1654     FIXME("(%p)->(%p %s %s %s %s %p %s)\n", This, uri, debugstr_variant(flags), debugstr_variant(target_frame),
1655           debugstr_variant(post_data), debugstr_variant(headers), bind_ctx, debugstr_w(url_fragment));
1656     return E_NOTIMPL;
1657 }
1658 
1659 static const IWebBrowserPriv2IE9Vtbl WebBrowserPriv2IE9Vtbl = {
1660     WebBrowserPriv2IE9_QueryInterface,
1661     WebBrowserPriv2IE9_AddRef,
1662     WebBrowserPriv2IE9_Release,
1663     WebBrowserPriv2IE9_NavigateWithBindCtx2
1664 };
1665 
1666 BOOL HlinkFrame_QI(HlinkFrame *This, REFIID riid, void **ppv)
1667 {
1668     if(IsEqualGUID(&IID_IHlinkFrame, riid)) {
1669         TRACE("(%p)->(IID_IHlinkFrame %p)\n", This, ppv);
1670         *ppv = &This->IHlinkFrame_iface;
1671     }else if(IsEqualGUID(&IID_ITargetFrame, riid)) {
1672         TRACE("(%p)->(IID_ITargetFrame %p)\n", This, ppv);
1673         *ppv = &This->ITargetFrame_iface;
1674     }else if(IsEqualGUID(&IID_ITargetFrame2, riid)) {
1675         TRACE("(%p)->(IID_ITargetFrame2 %p)\n", This, ppv);
1676         *ppv = &This->ITargetFrame2_iface;
1677     }else if(IsEqualGUID(&IID_ITargetFramePriv, riid)) {
1678         TRACE("(%p)->(IID_ITargetFramePriv %p)\n", This, ppv);
1679         *ppv = &This->ITargetFramePriv2_iface;
1680     }else if(IsEqualGUID(&IID_ITargetFramePriv2, riid)) {
1681         TRACE("(%p)->(IID_ITargetFramePriv2 %p)\n", This, ppv);
1682         *ppv = &This->ITargetFramePriv2_iface;
1683     }else if(IsEqualGUID(&IID_IWebBrowserPriv2IE9, riid)) {
1684         TRACE("(%p)->(IID_IWebBrowserPriv2IE9 %p)\n", This, ppv);
1685         *ppv = &This->IWebBrowserPriv2IE9_iface;
1686     }else {
1687         return FALSE;
1688     }
1689 
1690     IUnknown_AddRef((IUnknown*)*ppv);
1691     return TRUE;
1692 }
1693 
1694 void HlinkFrame_Init(HlinkFrame *This, IUnknown *outer, DocHost *doc_host)
1695 {
1696     This->IHlinkFrame_iface.lpVtbl = &HlinkFrameVtbl;
1697     This->ITargetFrame_iface.lpVtbl = &TargetFrameVtbl;
1698     This->ITargetFrame2_iface.lpVtbl = &TargetFrame2Vtbl;
1699     This->ITargetFramePriv2_iface.lpVtbl = &TargetFramePriv2Vtbl;
1700     This->IWebBrowserPriv2IE9_iface.lpVtbl = &WebBrowserPriv2IE9Vtbl;
1701 
1702     This->outer = outer;
1703     This->doc_host = doc_host;
1704 }
1705