shdocvw: Added beginning IHlinkFrame::Navigate implementation.
[wine] / dlls / shdocvw / navigate.c
1 /*
2  * Copyright 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #define NONAMELESSUNION
20 #define NONAMELESSSTRUCT
21
22 #include "wine/debug.h"
23 #include "wine/unicode.h"
24
25 #include "shdocvw.h"
26 #include "mshtml.h"
27 #include "exdispid.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
30
31 static void dump_BINDINFO(BINDINFO *bi)
32 {
33     static const char *BINDINFOF_str[] = {
34         "#0",
35         "BINDINFOF_URLENCODESTGMEDDATA",
36         "BINDINFOF_URLENCODEDEXTRAINFO"
37     };
38
39     static const char *BINDVERB_str[] = {
40         "BINDVERB_GET",
41         "BINDVERB_POST",
42         "BINDVERB_PUT",
43         "BINDVERB_CUSTOM"
44     };
45
46     TRACE("\n"
47             "BINDINFO = {\n"
48             "    %ld, %s,\n"
49             "    {%ld, %p, %p},\n"
50             "    %s,\n"
51             "    %s,\n"
52             "    %s,\n"
53             "    %ld, %08lx, %ld, %ld\n"
54             "    {%ld %p %x},\n"
55             "    %s\n"
56             "    %p, %ld\n"
57             "}\n",
58
59             bi->cbSize, debugstr_w(bi->szExtraInfo),
60             bi->stgmedData.tymed, bi->stgmedData.u.hGlobal, bi->stgmedData.pUnkForRelease,
61             bi->grfBindInfoF > BINDINFOF_URLENCODEDEXTRAINFO
62                 ? "unknown" : BINDINFOF_str[bi->grfBindInfoF],
63             bi->dwBindVerb > BINDVERB_CUSTOM
64                 ? "unknown" : BINDVERB_str[bi->dwBindVerb],
65             debugstr_w(bi->szCustomVerb),
66             bi->cbStgmedData, bi->dwOptions, bi->dwOptionsFlags, bi->dwCodePage,
67             bi->securityAttributes.nLength,
68             bi->securityAttributes.lpSecurityDescriptor,
69             bi->securityAttributes.bInheritHandle,
70             debugstr_guid(&bi->iid),
71             bi->pUnk, bi->dwReserved
72             );
73 }
74
75
76 static void on_before_navigate2(WebBrowser *This, PBYTE post_data, ULONG post_data_len,
77                                 LPWSTR headers, VARIANT_BOOL *cancel)
78 {
79     VARIANT var_url, var_flags, var_frame_name, var_post_data, var_post_data2, var_headers;
80     DISPPARAMS dispparams;
81     VARIANTARG params[7];
82
83     dispparams.cArgs = 7;
84     dispparams.cNamedArgs = 0;
85     dispparams.rgdispidNamedArgs = NULL;
86     dispparams.rgvarg = params;
87
88     V_VT(params) = VT_BOOL|VT_BYREF;
89     V_BOOLREF(params) = cancel;
90
91     V_VT(params+1) = (VT_BYREF|VT_VARIANT);
92     V_VARIANTREF(params+1) = &var_headers;
93     V_VT(&var_headers) = VT_BSTR;
94     V_BSTR(&var_headers) = headers;
95
96     V_VT(params+2) = (VT_BYREF|VT_VARIANT);
97     V_VARIANTREF(params+2) = &var_post_data2;
98     V_VT(&var_post_data2) = (VT_BYREF|VT_VARIANT);
99     V_VARIANTREF(&var_post_data2) = &var_post_data;
100     VariantInit(&var_post_data);
101
102     if(post_data_len) {
103         SAFEARRAYBOUND bound = {post_data_len, 0};
104         void *data;
105
106         V_VT(&var_post_data) = VT_UI1|VT_ARRAY;
107         V_ARRAY(&var_post_data) = SafeArrayCreate(VT_UI1, 1, &bound);
108
109         SafeArrayAccessData(V_ARRAY(&var_post_data), &data);
110         memcpy(data, post_data, post_data_len);
111         SafeArrayUnaccessData(V_ARRAY(&var_post_data));
112     }
113
114     V_VT(params+3) = (VT_BYREF|VT_VARIANT);
115     V_VARIANTREF(params+3) = &var_frame_name;
116     V_VT(&var_frame_name) = VT_BSTR;
117     V_BSTR(&var_frame_name) = NULL;
118
119     V_VT(params+4) = (VT_BYREF|VT_VARIANT);
120     V_VARIANTREF(params+4) = &var_flags;
121     V_VT(&var_flags) = VT_I4;
122     V_I4(&var_flags) = 0;
123
124     V_VT(params+5) = (VT_BYREF|VT_VARIANT);
125     V_VARIANTREF(params+5) = &var_url;
126     V_VT(&var_url) = VT_BSTR;
127     V_BSTR(&var_url) = SysAllocString(This->url);
128
129     V_VT(params+6) = (VT_DISPATCH);
130     V_DISPATCH(params+6) = (IDispatch*)WEBBROWSER2(This);
131
132     call_sink(This->cp_wbe2, DISPID_BEFORENAVIGATE2, &dispparams);
133
134     if(post_data_len)
135         SafeArrayDestroy(V_ARRAY(&var_post_data));
136
137 }
138
139 static HRESULT navigate(WebBrowser *This, IMoniker *mon, IBindCtx *bindctx,
140                         IBindStatusCallback *callback)
141 {
142     IOleObject *oleobj;
143     IPersistMoniker *persist;
144     VARIANT_BOOL cancel = VARIANT_FALSE;
145     HRESULT hres;
146
147     if(cancel) {
148         FIXME("Cancel\n");
149         return S_OK;
150     }
151
152     IBindCtx_RegisterObjectParam(bindctx, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM,
153                                  (IUnknown*)CLIENTSITE(This));
154
155     /*
156      * FIXME:
157      * We should use URLMoniker's BindToObject instead creating HTMLDocument here.
158      * This should be fixed when mshtml.dll and urlmon.dll will be good enough.
159      */
160
161     if(This->document)
162         deactivate_document(This);
163
164     hres = CoCreateInstance(&CLSID_HTMLDocument, NULL,
165                             CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
166                             &IID_IUnknown, (void**)&This->document);
167
168     if(FAILED(hres)) {
169         WARN("Could not create HTMLDocument: %08lx\n", hres);
170         return hres;
171     }
172
173     hres = IUnknown_QueryInterface(This->document, &IID_IPersistMoniker, (void**)&persist);
174     if(FAILED(hres))
175         return hres;
176
177     if(FAILED(hres)) {
178         IPersistMoniker_Release(persist);
179         return hres;
180     }
181
182     hres = IPersistMoniker_Load(persist, FALSE, mon, bindctx, 0);
183     IPersistMoniker_Release(persist);
184     if(FAILED(hres)) {
185         WARN("Load failed: %08lx\n", hres);
186         return hres;
187     }
188
189     hres = IUnknown_QueryInterface(This->document, &IID_IOleObject, (void**)&oleobj);
190     if(FAILED(hres))
191         return hres;
192
193     hres = IOleObject_SetClientSite(oleobj, CLIENTSITE(This));
194     IOleObject_Release(oleobj);
195
196     PostMessageW(This->doc_view_hwnd, WB_WM_NAVIGATE2, 0, 0);
197
198     return hres;
199 }
200
201 HRESULT navigate_hlink(WebBrowser *This, IMoniker *mon, IBindCtx *bindctx,
202                        IBindStatusCallback *callback)
203 {
204     IHttpNegotiate *http_negotiate;
205     PBYTE post_data = NULL;
206     ULONG post_data_len = 0;
207     LPWSTR headers = NULL;
208     VARIANT_BOOL cancel = VARIANT_FALSE;
209     BINDINFO bindinfo;
210     DWORD bindf = 0;
211     HRESULT hres;
212
213     IMoniker_GetDisplayName(mon, NULL, NULL, &This->url);
214     TRACE("navigating to %s\n", debugstr_w(This->url));
215
216     hres = IBindStatusCallback_QueryInterface(callback, &IID_IHttpNegotiate,
217                                               (void**)&http_negotiate);
218     if(SUCCEEDED(hres)) {
219         static const WCHAR null_string[] = {0};
220
221         IHttpNegotiate_BeginningTransaction(http_negotiate, null_string, null_string, 0,
222                                             &headers);
223         IHttpNegotiate_Release(http_negotiate);
224     }
225
226     memset(&bindinfo, 0, sizeof(bindinfo));
227     bindinfo.cbSize = sizeof(bindinfo);
228
229     hres = IBindStatusCallback_GetBindInfo(callback, &bindf, &bindinfo);
230     if(bindinfo.dwBindVerb == BINDVERB_POST) {
231         post_data_len = bindinfo.cbStgmedData;
232         if(post_data_len)
233             post_data = bindinfo.stgmedData.u.hGlobal;
234     }
235
236     on_before_navigate2(This, post_data, post_data_len, headers, &cancel);
237
238     CoTaskMemFree(headers);
239     ReleaseBindInfo(&bindinfo);
240
241     if(cancel) {
242         FIXME("navigation canceled\n");
243         return S_OK;
244     }
245
246     return navigate(This, mon, bindctx, callback);
247 }
248
249 #define HLINKFRAME_THIS(iface) DEFINE_THIS(WebBrowser, HlinkFrame, iface)
250
251 static HRESULT WINAPI HlinkFrame_QueryInterface(IHlinkFrame *iface, REFIID riid, void **ppv)
252 {
253     WebBrowser *This = HLINKFRAME_THIS(iface);
254     return IWebBrowser2_QueryInterface(WEBBROWSER2(This), riid, ppv);
255 }
256
257 static ULONG WINAPI HlinkFrame_AddRef(IHlinkFrame *iface)
258 {
259     WebBrowser *This = HLINKFRAME_THIS(iface);
260     return IWebBrowser2_AddRef(WEBBROWSER2(This));
261 }
262
263 static ULONG WINAPI HlinkFrame_Release(IHlinkFrame *iface)
264 {
265     WebBrowser *This = HLINKFRAME_THIS(iface);
266     return IWebBrowser2_Release(WEBBROWSER2(This));
267 }
268
269 static HRESULT WINAPI HlinkFrame_SetBrowseContext(IHlinkFrame *iface,
270                                                   IHlinkBrowseContext *pihlbc)
271 {
272     WebBrowser *This = HLINKFRAME_THIS(iface);
273     FIXME("(%p)->(%p)\n", This, pihlbc);
274     return E_NOTIMPL;
275 }
276
277 static HRESULT WINAPI HlinkFrame_GetBrowseContext(IHlinkFrame *iface,
278                                                   IHlinkBrowseContext **ppihlbc)
279 {
280     WebBrowser *This = HLINKFRAME_THIS(iface);
281     FIXME("(%p)->(%p)\n", This, ppihlbc);
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI HlinkFrame_Navigate(IHlinkFrame *iface, DWORD grfHLNF, LPBC pbc,
286                                           IBindStatusCallback *pibsc, IHlink *pihlNavigate)
287 {
288     WebBrowser *This = HLINKFRAME_THIS(iface);
289     IMoniker *mon;
290     LPWSTR location = NULL;
291     BINDINFO bi = {0};
292     DWORD bindf = 0;
293
294     TRACE("(%p)->(%08lx %p %p %p)\n", This, grfHLNF, pbc, pibsc, pihlNavigate);
295
296     if(grfHLNF)
297         FIXME("unsupported grfHLNF=%08lx\n", grfHLNF);
298
299     /* Windows calls GetTargetFrameName here. */
300
301     memset(&bi, 0, sizeof(bi));
302     bi.cbSize = sizeof(bi);
303
304     IBindStatusCallback_GetBindInfo(pibsc, &bindf, &bi);
305     dump_BINDINFO(&bi);
306
307     IHlink_GetMonikerReference(pihlNavigate, 1, &mon, &location);
308
309     if(location) {
310         FIXME("location = %s\n", debugstr_w(location));
311         CoTaskMemFree(location);
312     }
313
314     /* Windows calls GetHlinkSite here */
315
316     return navigate_hlink(This, mon, pbc, pibsc);
317 }
318
319 static HRESULT WINAPI HlinkFrame_OnNavigate(IHlinkFrame *iface, DWORD grfHLNF,
320         IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, DWORD dwreserved)
321 {
322     WebBrowser *This = HLINKFRAME_THIS(iface);
323     FIXME("(%p)->(%08lx %p %s %s %ld)\n", This, grfHLNF, pimkTarget, debugstr_w(pwzLocation),
324           debugstr_w(pwzFriendlyName), dwreserved);
325     return E_NOTIMPL;
326 }
327
328 static HRESULT WINAPI HlinkFrame_UpdateHlink(IHlinkFrame *iface, ULONG uHLID,
329         IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName)
330 {
331     WebBrowser *This = HLINKFRAME_THIS(iface);
332     FIXME("(%p)->(%lu %p %s %s)\n", This, uHLID, pimkTarget, debugstr_w(pwzLocation),
333           debugstr_w(pwzFriendlyName));
334     return E_NOTIMPL;
335 }
336
337 #undef HLINKFRAME_THIS
338
339 static const IHlinkFrameVtbl HlinkFrameVtbl = {
340     HlinkFrame_QueryInterface,
341     HlinkFrame_AddRef,
342     HlinkFrame_Release,
343     HlinkFrame_SetBrowseContext,
344     HlinkFrame_GetBrowseContext,
345     HlinkFrame_Navigate,
346     HlinkFrame_OnNavigate,
347     HlinkFrame_UpdateHlink
348 };
349
350 void WebBrowser_HlinkFrame_Init(WebBrowser *This)
351 {
352     This->lpHlinkFrameVtbl = &HlinkFrameVtbl;
353 }