xref: /reactos/dll/win32/mshtml/navigate.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * Copyright 2006-2010 Jacek Caban for CodeWeavers
3*c2c66affSColin Finck  *
4*c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5*c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6*c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7*c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8*c2c66affSColin Finck  *
9*c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10*c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*c2c66affSColin Finck  * Lesser General Public License for more details.
13*c2c66affSColin Finck  *
14*c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15*c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16*c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17*c2c66affSColin Finck  */
18*c2c66affSColin Finck 
19*c2c66affSColin Finck #include "mshtml_private.h"
20*c2c66affSColin Finck 
21*c2c66affSColin Finck #include <hlguids.h>
22*c2c66affSColin Finck #include <htiface.h>
23*c2c66affSColin Finck 
24*c2c66affSColin Finck #define CONTENT_LENGTH "Content-Length"
25*c2c66affSColin Finck #define UTF8_STR "utf-8"
26*c2c66affSColin Finck #define UTF16_STR "utf-16"
27*c2c66affSColin Finck 
28*c2c66affSColin Finck static const WCHAR emptyW[] = {0};
29*c2c66affSColin Finck static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
30*c2c66affSColin Finck 
31*c2c66affSColin Finck struct nsProtocolStream {
32*c2c66affSColin Finck     nsIInputStream nsIInputStream_iface;
33*c2c66affSColin Finck 
34*c2c66affSColin Finck     LONG ref;
35*c2c66affSColin Finck 
36*c2c66affSColin Finck     char buf[1024];
37*c2c66affSColin Finck     DWORD buf_size;
38*c2c66affSColin Finck };
39*c2c66affSColin Finck 
impl_from_nsIInputStream(nsIInputStream * iface)40*c2c66affSColin Finck static inline nsProtocolStream *impl_from_nsIInputStream(nsIInputStream *iface)
41*c2c66affSColin Finck {
42*c2c66affSColin Finck     return CONTAINING_RECORD(iface, nsProtocolStream, nsIInputStream_iface);
43*c2c66affSColin Finck }
44*c2c66affSColin Finck 
nsInputStream_QueryInterface(nsIInputStream * iface,nsIIDRef riid,void ** result)45*c2c66affSColin Finck static nsresult NSAPI nsInputStream_QueryInterface(nsIInputStream *iface, nsIIDRef riid,
46*c2c66affSColin Finck         void **result)
47*c2c66affSColin Finck {
48*c2c66affSColin Finck     nsProtocolStream *This = impl_from_nsIInputStream(iface);
49*c2c66affSColin Finck 
50*c2c66affSColin Finck     *result = NULL;
51*c2c66affSColin Finck 
52*c2c66affSColin Finck     if(IsEqualGUID(&IID_nsISupports, riid)) {
53*c2c66affSColin Finck         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
54*c2c66affSColin Finck         *result  = &This->nsIInputStream_iface;
55*c2c66affSColin Finck     }else if(IsEqualGUID(&IID_nsIInputStream, riid)) {
56*c2c66affSColin Finck         TRACE("(%p)->(IID_nsIInputStream %p)\n", This, result);
57*c2c66affSColin Finck         *result  = &This->nsIInputStream_iface;
58*c2c66affSColin Finck     }
59*c2c66affSColin Finck 
60*c2c66affSColin Finck     if(*result) {
61*c2c66affSColin Finck         nsIInputStream_AddRef(&This->nsIInputStream_iface);
62*c2c66affSColin Finck         return NS_OK;
63*c2c66affSColin Finck     }
64*c2c66affSColin Finck 
65*c2c66affSColin Finck     WARN("unsupported interface %s\n", debugstr_guid(riid));
66*c2c66affSColin Finck     return NS_NOINTERFACE;
67*c2c66affSColin Finck }
68*c2c66affSColin Finck 
nsInputStream_AddRef(nsIInputStream * iface)69*c2c66affSColin Finck static nsrefcnt NSAPI nsInputStream_AddRef(nsIInputStream *iface)
70*c2c66affSColin Finck {
71*c2c66affSColin Finck     nsProtocolStream *This = impl_from_nsIInputStream(iface);
72*c2c66affSColin Finck     LONG ref = InterlockedIncrement(&This->ref);
73*c2c66affSColin Finck 
74*c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
75*c2c66affSColin Finck 
76*c2c66affSColin Finck     return ref;
77*c2c66affSColin Finck }
78*c2c66affSColin Finck 
79*c2c66affSColin Finck 
nsInputStream_Release(nsIInputStream * iface)80*c2c66affSColin Finck static nsrefcnt NSAPI nsInputStream_Release(nsIInputStream *iface)
81*c2c66affSColin Finck {
82*c2c66affSColin Finck     nsProtocolStream *This = impl_from_nsIInputStream(iface);
83*c2c66affSColin Finck     LONG ref = InterlockedDecrement(&This->ref);
84*c2c66affSColin Finck 
85*c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
86*c2c66affSColin Finck 
87*c2c66affSColin Finck     if(!ref)
88*c2c66affSColin Finck         heap_free(This);
89*c2c66affSColin Finck 
90*c2c66affSColin Finck     return ref;
91*c2c66affSColin Finck }
92*c2c66affSColin Finck 
nsInputStream_Close(nsIInputStream * iface)93*c2c66affSColin Finck static nsresult NSAPI nsInputStream_Close(nsIInputStream *iface)
94*c2c66affSColin Finck {
95*c2c66affSColin Finck     nsProtocolStream *This = impl_from_nsIInputStream(iface);
96*c2c66affSColin Finck     FIXME("(%p)\n", This);
97*c2c66affSColin Finck     return NS_ERROR_NOT_IMPLEMENTED;
98*c2c66affSColin Finck }
99*c2c66affSColin Finck 
nsInputStream_Available(nsIInputStream * iface,UINT64 * _retval)100*c2c66affSColin Finck static nsresult NSAPI nsInputStream_Available(nsIInputStream *iface, UINT64 *_retval)
101*c2c66affSColin Finck {
102*c2c66affSColin Finck     nsProtocolStream *This = impl_from_nsIInputStream(iface);
103*c2c66affSColin Finck     FIXME("(%p)->(%p)\n", This, _retval);
104*c2c66affSColin Finck     return NS_ERROR_NOT_IMPLEMENTED;
105*c2c66affSColin Finck }
106*c2c66affSColin Finck 
nsInputStream_Read(nsIInputStream * iface,char * aBuf,UINT32 aCount,UINT32 * _retval)107*c2c66affSColin Finck static nsresult NSAPI nsInputStream_Read(nsIInputStream *iface, char *aBuf, UINT32 aCount,
108*c2c66affSColin Finck                                          UINT32 *_retval)
109*c2c66affSColin Finck {
110*c2c66affSColin Finck     nsProtocolStream *This = impl_from_nsIInputStream(iface);
111*c2c66affSColin Finck     DWORD read = aCount;
112*c2c66affSColin Finck 
113*c2c66affSColin Finck     TRACE("(%p)->(%p %d %p)\n", This, aBuf, aCount, _retval);
114*c2c66affSColin Finck 
115*c2c66affSColin Finck     if(read > This->buf_size)
116*c2c66affSColin Finck         read = This->buf_size;
117*c2c66affSColin Finck 
118*c2c66affSColin Finck     if(read) {
119*c2c66affSColin Finck         memcpy(aBuf, This->buf, read);
120*c2c66affSColin Finck         if(read < This->buf_size)
121*c2c66affSColin Finck             memmove(This->buf, This->buf+read, This->buf_size-read);
122*c2c66affSColin Finck         This->buf_size -= read;
123*c2c66affSColin Finck     }
124*c2c66affSColin Finck 
125*c2c66affSColin Finck     *_retval = read;
126*c2c66affSColin Finck     return NS_OK;
127*c2c66affSColin Finck }
128*c2c66affSColin Finck 
nsInputStream_ReadSegments(nsIInputStream * iface,nsresult (WINAPI * aWriter)(nsIInputStream *,void *,const char *,UINT32,UINT32,UINT32 *),void * aClousure,UINT32 aCount,UINT32 * _retval)129*c2c66affSColin Finck static nsresult NSAPI nsInputStream_ReadSegments(nsIInputStream *iface,
130*c2c66affSColin Finck         nsresult (WINAPI *aWriter)(nsIInputStream*,void*,const char*,UINT32,UINT32,UINT32*),
131*c2c66affSColin Finck         void *aClousure, UINT32 aCount, UINT32 *_retval)
132*c2c66affSColin Finck {
133*c2c66affSColin Finck     nsProtocolStream *This = impl_from_nsIInputStream(iface);
134*c2c66affSColin Finck     UINT32 written = 0;
135*c2c66affSColin Finck     nsresult nsres;
136*c2c66affSColin Finck 
137*c2c66affSColin Finck     TRACE("(%p)->(%p %p %d %p)\n", This, aWriter, aClousure, aCount, _retval);
138*c2c66affSColin Finck 
139*c2c66affSColin Finck     if(!This->buf_size)
140*c2c66affSColin Finck         return S_OK;
141*c2c66affSColin Finck 
142*c2c66affSColin Finck     if(aCount > This->buf_size)
143*c2c66affSColin Finck         aCount = This->buf_size;
144*c2c66affSColin Finck 
145*c2c66affSColin Finck     nsres = aWriter(&This->nsIInputStream_iface, aClousure, This->buf, 0, aCount, &written);
146*c2c66affSColin Finck     if(NS_FAILED(nsres))
147*c2c66affSColin Finck         TRACE("aWriter failed: %08x\n", nsres);
148*c2c66affSColin Finck     else if(written != This->buf_size)
149*c2c66affSColin Finck         FIXME("written %d != buf_size %d\n", written, This->buf_size);
150*c2c66affSColin Finck 
151*c2c66affSColin Finck     This->buf_size -= written;
152*c2c66affSColin Finck 
153*c2c66affSColin Finck     *_retval = written;
154*c2c66affSColin Finck     return nsres;
155*c2c66affSColin Finck }
156*c2c66affSColin Finck 
nsInputStream_IsNonBlocking(nsIInputStream * iface,cpp_bool * _retval)157*c2c66affSColin Finck static nsresult NSAPI nsInputStream_IsNonBlocking(nsIInputStream *iface, cpp_bool *_retval)
158*c2c66affSColin Finck {
159*c2c66affSColin Finck     nsProtocolStream *This = impl_from_nsIInputStream(iface);
160*c2c66affSColin Finck     FIXME("(%p)->(%p)\n", This, _retval);
161*c2c66affSColin Finck     return NS_ERROR_NOT_IMPLEMENTED;
162*c2c66affSColin Finck }
163*c2c66affSColin Finck 
164*c2c66affSColin Finck static const nsIInputStreamVtbl nsInputStreamVtbl = {
165*c2c66affSColin Finck     nsInputStream_QueryInterface,
166*c2c66affSColin Finck     nsInputStream_AddRef,
167*c2c66affSColin Finck     nsInputStream_Release,
168*c2c66affSColin Finck     nsInputStream_Close,
169*c2c66affSColin Finck     nsInputStream_Available,
170*c2c66affSColin Finck     nsInputStream_Read,
171*c2c66affSColin Finck     nsInputStream_ReadSegments,
172*c2c66affSColin Finck     nsInputStream_IsNonBlocking
173*c2c66affSColin Finck };
174*c2c66affSColin Finck 
create_nsprotocol_stream(void)175*c2c66affSColin Finck static nsProtocolStream *create_nsprotocol_stream(void)
176*c2c66affSColin Finck {
177*c2c66affSColin Finck     nsProtocolStream *ret;
178*c2c66affSColin Finck 
179*c2c66affSColin Finck     ret = heap_alloc(sizeof(nsProtocolStream));
180*c2c66affSColin Finck     if(!ret)
181*c2c66affSColin Finck         return NULL;
182*c2c66affSColin Finck 
183*c2c66affSColin Finck     ret->nsIInputStream_iface.lpVtbl = &nsInputStreamVtbl;
184*c2c66affSColin Finck     ret->ref = 1;
185*c2c66affSColin Finck     ret->buf_size = 0;
186*c2c66affSColin Finck 
187*c2c66affSColin Finck     return ret;
188*c2c66affSColin Finck }
189*c2c66affSColin Finck 
release_request_data(request_data_t * request_data)190*c2c66affSColin Finck static void release_request_data(request_data_t *request_data)
191*c2c66affSColin Finck {
192*c2c66affSColin Finck     if(request_data->post_stream)
193*c2c66affSColin Finck         nsIInputStream_Release(request_data->post_stream);
194*c2c66affSColin Finck     heap_free(request_data->headers);
195*c2c66affSColin Finck     if(request_data->post_data)
196*c2c66affSColin Finck         GlobalFree(request_data->post_data);
197*c2c66affSColin Finck }
198*c2c66affSColin Finck 
impl_from_IBindStatusCallback(IBindStatusCallback * iface)199*c2c66affSColin Finck static inline BSCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
200*c2c66affSColin Finck {
201*c2c66affSColin Finck     return CONTAINING_RECORD(iface, BSCallback, IBindStatusCallback_iface);
202*c2c66affSColin Finck }
203*c2c66affSColin Finck 
BindStatusCallback_QueryInterface(IBindStatusCallback * iface,REFIID riid,void ** ppv)204*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
205*c2c66affSColin Finck         REFIID riid, void **ppv)
206*c2c66affSColin Finck {
207*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
208*c2c66affSColin Finck 
209*c2c66affSColin Finck     *ppv = NULL;
210*c2c66affSColin Finck     if(IsEqualGUID(&IID_IUnknown, riid)) {
211*c2c66affSColin Finck         TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
212*c2c66affSColin Finck         *ppv = &This->IBindStatusCallback_iface;
213*c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
214*c2c66affSColin Finck         TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
215*c2c66affSColin Finck         *ppv = &This->IBindStatusCallback_iface;
216*c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
217*c2c66affSColin Finck         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
218*c2c66affSColin Finck         *ppv = &This->IServiceProvider_iface;
219*c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
220*c2c66affSColin Finck         TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv);
221*c2c66affSColin Finck         *ppv = &This->IHttpNegotiate2_iface;
222*c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
223*c2c66affSColin Finck         TRACE("(%p)->(IID_IHttpNegotiate2 %p)\n", This, ppv);
224*c2c66affSColin Finck         *ppv = &This->IHttpNegotiate2_iface;
225*c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
226*c2c66affSColin Finck         TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
227*c2c66affSColin Finck         *ppv = &This->IInternetBindInfo_iface;
228*c2c66affSColin Finck     }
229*c2c66affSColin Finck 
230*c2c66affSColin Finck     if(*ppv) {
231*c2c66affSColin Finck         IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
232*c2c66affSColin Finck         return S_OK;
233*c2c66affSColin Finck     }
234*c2c66affSColin Finck 
235*c2c66affSColin Finck     TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
236*c2c66affSColin Finck     return E_NOINTERFACE;
237*c2c66affSColin Finck }
238*c2c66affSColin Finck 
BindStatusCallback_AddRef(IBindStatusCallback * iface)239*c2c66affSColin Finck static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
240*c2c66affSColin Finck {
241*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
242*c2c66affSColin Finck     LONG ref = InterlockedIncrement(&This->ref);
243*c2c66affSColin Finck 
244*c2c66affSColin Finck     TRACE("(%p) ref = %d\n", This, ref);
245*c2c66affSColin Finck 
246*c2c66affSColin Finck     return ref;
247*c2c66affSColin Finck }
248*c2c66affSColin Finck 
BindStatusCallback_Release(IBindStatusCallback * iface)249*c2c66affSColin Finck static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
250*c2c66affSColin Finck {
251*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
252*c2c66affSColin Finck     LONG ref = InterlockedDecrement(&This->ref);
253*c2c66affSColin Finck 
254*c2c66affSColin Finck     TRACE("(%p) ref = %d\n", This, ref);
255*c2c66affSColin Finck 
256*c2c66affSColin Finck     if(!ref) {
257*c2c66affSColin Finck         release_request_data(&This->request_data);
258*c2c66affSColin Finck         if(This->mon)
259*c2c66affSColin Finck             IMoniker_Release(This->mon);
260*c2c66affSColin Finck         if(This->binding)
261*c2c66affSColin Finck             IBinding_Release(This->binding);
262*c2c66affSColin Finck         list_remove(&This->entry);
263*c2c66affSColin Finck         list_init(&This->entry);
264*c2c66affSColin Finck 
265*c2c66affSColin Finck         This->vtbl->destroy(This);
266*c2c66affSColin Finck     }
267*c2c66affSColin Finck 
268*c2c66affSColin Finck     return ref;
269*c2c66affSColin Finck }
270*c2c66affSColin Finck 
BindStatusCallback_OnStartBinding(IBindStatusCallback * iface,DWORD dwReserved,IBinding * pbind)271*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
272*c2c66affSColin Finck         DWORD dwReserved, IBinding *pbind)
273*c2c66affSColin Finck {
274*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
275*c2c66affSColin Finck 
276*c2c66affSColin Finck     TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
277*c2c66affSColin Finck 
278*c2c66affSColin Finck     IBinding_AddRef(pbind);
279*c2c66affSColin Finck     This->binding = pbind;
280*c2c66affSColin Finck 
281*c2c66affSColin Finck     if(This->window)
282*c2c66affSColin Finck         list_add_head(&This->window->bindings, &This->entry);
283*c2c66affSColin Finck 
284*c2c66affSColin Finck     return This->vtbl->start_binding(This);
285*c2c66affSColin Finck }
286*c2c66affSColin Finck 
BindStatusCallback_GetPriority(IBindStatusCallback * iface,LONG * pnPriority)287*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
288*c2c66affSColin Finck {
289*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
290*c2c66affSColin Finck     FIXME("(%p)->(%p)\n", This, pnPriority);
291*c2c66affSColin Finck     return E_NOTIMPL;
292*c2c66affSColin Finck }
293*c2c66affSColin Finck 
BindStatusCallback_OnLowResource(IBindStatusCallback * iface,DWORD reserved)294*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
295*c2c66affSColin Finck {
296*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
297*c2c66affSColin Finck     FIXME("(%p)->(%d)\n", This, reserved);
298*c2c66affSColin Finck     return E_NOTIMPL;
299*c2c66affSColin Finck }
300*c2c66affSColin Finck 
BindStatusCallback_OnProgress(IBindStatusCallback * iface,ULONG ulProgress,ULONG ulProgressMax,ULONG ulStatusCode,LPCWSTR szStatusText)301*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
302*c2c66affSColin Finck         ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
303*c2c66affSColin Finck {
304*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
305*c2c66affSColin Finck 
306*c2c66affSColin Finck     TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
307*c2c66affSColin Finck             debugstr_w(szStatusText));
308*c2c66affSColin Finck 
309*c2c66affSColin Finck     return This->vtbl->on_progress(This, ulStatusCode, szStatusText);
310*c2c66affSColin Finck }
311*c2c66affSColin Finck 
BindStatusCallback_OnStopBinding(IBindStatusCallback * iface,HRESULT hresult,LPCWSTR szError)312*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface,
313*c2c66affSColin Finck         HRESULT hresult, LPCWSTR szError)
314*c2c66affSColin Finck {
315*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
316*c2c66affSColin Finck     HRESULT hres;
317*c2c66affSColin Finck 
318*c2c66affSColin Finck     TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
319*c2c66affSColin Finck 
320*c2c66affSColin Finck     /* NOTE: IE7 calls GetBindResult here */
321*c2c66affSColin Finck 
322*c2c66affSColin Finck     hres = This->vtbl->stop_binding(This, hresult);
323*c2c66affSColin Finck 
324*c2c66affSColin Finck     if(This->binding) {
325*c2c66affSColin Finck         IBinding_Release(This->binding);
326*c2c66affSColin Finck         This->binding = NULL;
327*c2c66affSColin Finck     }
328*c2c66affSColin Finck 
329*c2c66affSColin Finck     if(This->mon) {
330*c2c66affSColin Finck         IMoniker_Release(This->mon);
331*c2c66affSColin Finck         This->mon = NULL;
332*c2c66affSColin Finck     }
333*c2c66affSColin Finck 
334*c2c66affSColin Finck     list_remove(&This->entry);
335*c2c66affSColin Finck     list_init(&This->entry);
336*c2c66affSColin Finck     This->window = NULL;
337*c2c66affSColin Finck 
338*c2c66affSColin Finck     return hres;
339*c2c66affSColin Finck }
340*c2c66affSColin Finck 
BindStatusCallback_GetBindInfo(IBindStatusCallback * iface,DWORD * grfBINDF,BINDINFO * pbindinfo)341*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
342*c2c66affSColin Finck         DWORD *grfBINDF, BINDINFO *pbindinfo)
343*c2c66affSColin Finck {
344*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
345*c2c66affSColin Finck     DWORD size;
346*c2c66affSColin Finck 
347*c2c66affSColin Finck     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
348*c2c66affSColin Finck 
349*c2c66affSColin Finck     if(!This->bindinfo_ready) {
350*c2c66affSColin Finck         HRESULT hres;
351*c2c66affSColin Finck 
352*c2c66affSColin Finck         hres = This->vtbl->init_bindinfo(This);
353*c2c66affSColin Finck         if(FAILED(hres))
354*c2c66affSColin Finck             return hres;
355*c2c66affSColin Finck 
356*c2c66affSColin Finck         This->bindinfo_ready = TRUE;
357*c2c66affSColin Finck     }
358*c2c66affSColin Finck 
359*c2c66affSColin Finck     *grfBINDF = This->bindf;
360*c2c66affSColin Finck 
361*c2c66affSColin Finck     size = pbindinfo->cbSize;
362*c2c66affSColin Finck     memset(pbindinfo, 0, size);
363*c2c66affSColin Finck     pbindinfo->cbSize = size;
364*c2c66affSColin Finck 
365*c2c66affSColin Finck     pbindinfo->cbstgmedData = This->request_data.post_data_len;
366*c2c66affSColin Finck     pbindinfo->dwCodePage = CP_UTF8;
367*c2c66affSColin Finck     pbindinfo->dwOptions = 0x80000;
368*c2c66affSColin Finck 
369*c2c66affSColin Finck     if(This->request_data.post_data_len) {
370*c2c66affSColin Finck         pbindinfo->dwBindVerb = BINDVERB_POST;
371*c2c66affSColin Finck 
372*c2c66affSColin Finck         pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
373*c2c66affSColin Finck         pbindinfo->stgmedData.u.hGlobal = This->request_data.post_data;
374*c2c66affSColin Finck         pbindinfo->stgmedData.pUnkForRelease = (IUnknown*)&This->IBindStatusCallback_iface;
375*c2c66affSColin Finck         IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
376*c2c66affSColin Finck     }
377*c2c66affSColin Finck 
378*c2c66affSColin Finck     return S_OK;
379*c2c66affSColin Finck }
380*c2c66affSColin Finck 
BindStatusCallback_OnDataAvailable(IBindStatusCallback * iface,DWORD grfBSCF,DWORD dwSize,FORMATETC * pformatetc,STGMEDIUM * pstgmed)381*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
382*c2c66affSColin Finck         DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
383*c2c66affSColin Finck {
384*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
385*c2c66affSColin Finck 
386*c2c66affSColin Finck     TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
387*c2c66affSColin Finck 
388*c2c66affSColin Finck     return This->vtbl->read_data(This, pstgmed->u.pstm);
389*c2c66affSColin Finck }
390*c2c66affSColin Finck 
BindStatusCallback_OnObjectAvailable(IBindStatusCallback * iface,REFIID riid,IUnknown * punk)391*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
392*c2c66affSColin Finck         REFIID riid, IUnknown *punk)
393*c2c66affSColin Finck {
394*c2c66affSColin Finck     BSCallback *This = impl_from_IBindStatusCallback(iface);
395*c2c66affSColin Finck     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
396*c2c66affSColin Finck     return E_NOTIMPL;
397*c2c66affSColin Finck }
398*c2c66affSColin Finck 
399*c2c66affSColin Finck static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
400*c2c66affSColin Finck     BindStatusCallback_QueryInterface,
401*c2c66affSColin Finck     BindStatusCallback_AddRef,
402*c2c66affSColin Finck     BindStatusCallback_Release,
403*c2c66affSColin Finck     BindStatusCallback_OnStartBinding,
404*c2c66affSColin Finck     BindStatusCallback_GetPriority,
405*c2c66affSColin Finck     BindStatusCallback_OnLowResource,
406*c2c66affSColin Finck     BindStatusCallback_OnProgress,
407*c2c66affSColin Finck     BindStatusCallback_OnStopBinding,
408*c2c66affSColin Finck     BindStatusCallback_GetBindInfo,
409*c2c66affSColin Finck     BindStatusCallback_OnDataAvailable,
410*c2c66affSColin Finck     BindStatusCallback_OnObjectAvailable
411*c2c66affSColin Finck };
412*c2c66affSColin Finck 
impl_from_IHttpNegotiate2(IHttpNegotiate2 * iface)413*c2c66affSColin Finck static inline BSCallback *impl_from_IHttpNegotiate2(IHttpNegotiate2 *iface)
414*c2c66affSColin Finck {
415*c2c66affSColin Finck     return CONTAINING_RECORD(iface, BSCallback, IHttpNegotiate2_iface);
416*c2c66affSColin Finck }
417*c2c66affSColin Finck 
HttpNegotiate_QueryInterface(IHttpNegotiate2 * iface,REFIID riid,void ** ppv)418*c2c66affSColin Finck static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
419*c2c66affSColin Finck                                                    REFIID riid, void **ppv)
420*c2c66affSColin Finck {
421*c2c66affSColin Finck     BSCallback *This = impl_from_IHttpNegotiate2(iface);
422*c2c66affSColin Finck     return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
423*c2c66affSColin Finck }
424*c2c66affSColin Finck 
HttpNegotiate_AddRef(IHttpNegotiate2 * iface)425*c2c66affSColin Finck static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
426*c2c66affSColin Finck {
427*c2c66affSColin Finck     BSCallback *This = impl_from_IHttpNegotiate2(iface);
428*c2c66affSColin Finck     return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
429*c2c66affSColin Finck }
430*c2c66affSColin Finck 
HttpNegotiate_Release(IHttpNegotiate2 * iface)431*c2c66affSColin Finck static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
432*c2c66affSColin Finck {
433*c2c66affSColin Finck     BSCallback *This = impl_from_IHttpNegotiate2(iface);
434*c2c66affSColin Finck     return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
435*c2c66affSColin Finck }
436*c2c66affSColin Finck 
HttpNegotiate_BeginningTransaction(IHttpNegotiate2 * iface,LPCWSTR szURL,LPCWSTR szHeaders,DWORD dwReserved,LPWSTR * pszAdditionalHeaders)437*c2c66affSColin Finck static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
438*c2c66affSColin Finck         LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
439*c2c66affSColin Finck {
440*c2c66affSColin Finck     BSCallback *This = impl_from_IHttpNegotiate2(iface);
441*c2c66affSColin Finck     HRESULT hres;
442*c2c66affSColin Finck 
443*c2c66affSColin Finck     TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders),
444*c2c66affSColin Finck           dwReserved, pszAdditionalHeaders);
445*c2c66affSColin Finck 
446*c2c66affSColin Finck     *pszAdditionalHeaders = NULL;
447*c2c66affSColin Finck 
448*c2c66affSColin Finck     hres = This->vtbl->beginning_transaction(This, pszAdditionalHeaders);
449*c2c66affSColin Finck     if(hres != S_FALSE)
450*c2c66affSColin Finck         return hres;
451*c2c66affSColin Finck 
452*c2c66affSColin Finck     if(This->request_data.headers) {
453*c2c66affSColin Finck         DWORD size;
454*c2c66affSColin Finck 
455*c2c66affSColin Finck         size = (strlenW(This->request_data.headers)+1)*sizeof(WCHAR);
456*c2c66affSColin Finck         *pszAdditionalHeaders = CoTaskMemAlloc(size);
457*c2c66affSColin Finck         if(!*pszAdditionalHeaders)
458*c2c66affSColin Finck             return E_OUTOFMEMORY;
459*c2c66affSColin Finck         memcpy(*pszAdditionalHeaders, This->request_data.headers, size);
460*c2c66affSColin Finck     }
461*c2c66affSColin Finck 
462*c2c66affSColin Finck     return S_OK;
463*c2c66affSColin Finck }
464*c2c66affSColin Finck 
HttpNegotiate_OnResponse(IHttpNegotiate2 * iface,DWORD dwResponseCode,LPCWSTR szResponseHeaders,LPCWSTR szRequestHeaders,LPWSTR * pszAdditionalRequestHeaders)465*c2c66affSColin Finck static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
466*c2c66affSColin Finck         LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
467*c2c66affSColin Finck {
468*c2c66affSColin Finck     BSCallback *This = impl_from_IHttpNegotiate2(iface);
469*c2c66affSColin Finck 
470*c2c66affSColin Finck     TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
471*c2c66affSColin Finck           debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
472*c2c66affSColin Finck 
473*c2c66affSColin Finck     return This->vtbl->on_response(This, dwResponseCode, szResponseHeaders);
474*c2c66affSColin Finck }
475*c2c66affSColin Finck 
HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 * iface,BYTE * pbSecurityId,DWORD * pcbSecurityId,DWORD_PTR dwReserved)476*c2c66affSColin Finck static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
477*c2c66affSColin Finck         BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
478*c2c66affSColin Finck {
479*c2c66affSColin Finck     BSCallback *This = impl_from_IHttpNegotiate2(iface);
480*c2c66affSColin Finck     FIXME("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved);
481*c2c66affSColin Finck     return E_NOTIMPL;
482*c2c66affSColin Finck }
483*c2c66affSColin Finck 
484*c2c66affSColin Finck static const IHttpNegotiate2Vtbl HttpNegotiate2Vtbl = {
485*c2c66affSColin Finck     HttpNegotiate_QueryInterface,
486*c2c66affSColin Finck     HttpNegotiate_AddRef,
487*c2c66affSColin Finck     HttpNegotiate_Release,
488*c2c66affSColin Finck     HttpNegotiate_BeginningTransaction,
489*c2c66affSColin Finck     HttpNegotiate_OnResponse,
490*c2c66affSColin Finck     HttpNegotiate_GetRootSecurityId
491*c2c66affSColin Finck };
492*c2c66affSColin Finck 
impl_from_IInternetBindInfo(IInternetBindInfo * iface)493*c2c66affSColin Finck static inline BSCallback *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
494*c2c66affSColin Finck {
495*c2c66affSColin Finck     return CONTAINING_RECORD(iface, BSCallback, IInternetBindInfo_iface);
496*c2c66affSColin Finck }
497*c2c66affSColin Finck 
InternetBindInfo_QueryInterface(IInternetBindInfo * iface,REFIID riid,void ** ppv)498*c2c66affSColin Finck static HRESULT WINAPI InternetBindInfo_QueryInterface(IInternetBindInfo *iface,
499*c2c66affSColin Finck                                                       REFIID riid, void **ppv)
500*c2c66affSColin Finck {
501*c2c66affSColin Finck     BSCallback *This = impl_from_IInternetBindInfo(iface);
502*c2c66affSColin Finck     return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
503*c2c66affSColin Finck }
504*c2c66affSColin Finck 
InternetBindInfo_AddRef(IInternetBindInfo * iface)505*c2c66affSColin Finck static ULONG WINAPI InternetBindInfo_AddRef(IInternetBindInfo *iface)
506*c2c66affSColin Finck {
507*c2c66affSColin Finck     BSCallback *This = impl_from_IInternetBindInfo(iface);
508*c2c66affSColin Finck     return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
509*c2c66affSColin Finck }
510*c2c66affSColin Finck 
InternetBindInfo_Release(IInternetBindInfo * iface)511*c2c66affSColin Finck static ULONG WINAPI InternetBindInfo_Release(IInternetBindInfo *iface)
512*c2c66affSColin Finck {
513*c2c66affSColin Finck     BSCallback *This = impl_from_IInternetBindInfo(iface);
514*c2c66affSColin Finck     return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
515*c2c66affSColin Finck }
516*c2c66affSColin Finck 
InternetBindInfo_GetBindInfo(IInternetBindInfo * iface,DWORD * grfBINDF,BINDINFO * pbindinfo)517*c2c66affSColin Finck static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface,
518*c2c66affSColin Finck                                                    DWORD *grfBINDF, BINDINFO *pbindinfo)
519*c2c66affSColin Finck {
520*c2c66affSColin Finck     BSCallback *This = impl_from_IInternetBindInfo(iface);
521*c2c66affSColin Finck     FIXME("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
522*c2c66affSColin Finck     return E_NOTIMPL;
523*c2c66affSColin Finck }
524*c2c66affSColin Finck 
InternetBindInfo_GetBindString(IInternetBindInfo * iface,ULONG ulStringType,LPOLESTR * ppwzStr,ULONG cEl,ULONG * pcElFetched)525*c2c66affSColin Finck static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface,
526*c2c66affSColin Finck         ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
527*c2c66affSColin Finck {
528*c2c66affSColin Finck     BSCallback *This = impl_from_IInternetBindInfo(iface);
529*c2c66affSColin Finck     FIXME("(%p)->(%u %p %u %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
530*c2c66affSColin Finck     return E_NOTIMPL;
531*c2c66affSColin Finck }
532*c2c66affSColin Finck 
533*c2c66affSColin Finck static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
534*c2c66affSColin Finck     InternetBindInfo_QueryInterface,
535*c2c66affSColin Finck     InternetBindInfo_AddRef,
536*c2c66affSColin Finck     InternetBindInfo_Release,
537*c2c66affSColin Finck     InternetBindInfo_GetBindInfo,
538*c2c66affSColin Finck     InternetBindInfo_GetBindString
539*c2c66affSColin Finck };
540*c2c66affSColin Finck 
impl_from_IServiceProvider(IServiceProvider * iface)541*c2c66affSColin Finck static inline BSCallback *impl_from_IServiceProvider(IServiceProvider *iface)
542*c2c66affSColin Finck {
543*c2c66affSColin Finck     return CONTAINING_RECORD(iface, BSCallback, IServiceProvider_iface);
544*c2c66affSColin Finck }
545*c2c66affSColin Finck 
BSCServiceProvider_QueryInterface(IServiceProvider * iface,REFIID riid,void ** ppv)546*c2c66affSColin Finck static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
547*c2c66affSColin Finck                                                         REFIID riid, void **ppv)
548*c2c66affSColin Finck {
549*c2c66affSColin Finck     BSCallback *This = impl_from_IServiceProvider(iface);
550*c2c66affSColin Finck     return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
551*c2c66affSColin Finck }
552*c2c66affSColin Finck 
BSCServiceProvider_AddRef(IServiceProvider * iface)553*c2c66affSColin Finck static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
554*c2c66affSColin Finck {
555*c2c66affSColin Finck     BSCallback *This = impl_from_IServiceProvider(iface);
556*c2c66affSColin Finck     return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
557*c2c66affSColin Finck }
558*c2c66affSColin Finck 
BSCServiceProvider_Release(IServiceProvider * iface)559*c2c66affSColin Finck static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
560*c2c66affSColin Finck {
561*c2c66affSColin Finck     BSCallback *This = impl_from_IServiceProvider(iface);
562*c2c66affSColin Finck     return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
563*c2c66affSColin Finck }
564*c2c66affSColin Finck 
BSCServiceProvider_QueryService(IServiceProvider * iface,REFGUID guidService,REFIID riid,void ** ppv)565*c2c66affSColin Finck static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
566*c2c66affSColin Finck         REFGUID guidService, REFIID riid, void **ppv)
567*c2c66affSColin Finck {
568*c2c66affSColin Finck     BSCallback *This = impl_from_IServiceProvider(iface);
569*c2c66affSColin Finck 
570*c2c66affSColin Finck     TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
571*c2c66affSColin Finck 
572*c2c66affSColin Finck     if(This->window && IsEqualGUID(guidService, &IID_IWindowForBindingUI))
573*c2c66affSColin Finck         return IServiceProvider_QueryService(&This->window->base.IServiceProvider_iface, guidService, riid, ppv);
574*c2c66affSColin Finck     return E_NOINTERFACE;
575*c2c66affSColin Finck }
576*c2c66affSColin Finck 
577*c2c66affSColin Finck static const IServiceProviderVtbl ServiceProviderVtbl = {
578*c2c66affSColin Finck     BSCServiceProvider_QueryInterface,
579*c2c66affSColin Finck     BSCServiceProvider_AddRef,
580*c2c66affSColin Finck     BSCServiceProvider_Release,
581*c2c66affSColin Finck     BSCServiceProvider_QueryService
582*c2c66affSColin Finck };
583*c2c66affSColin Finck 
init_bscallback(BSCallback * This,const BSCallbackVtbl * vtbl,IMoniker * mon,DWORD bindf)584*c2c66affSColin Finck void init_bscallback(BSCallback *This, const BSCallbackVtbl *vtbl, IMoniker *mon, DWORD bindf)
585*c2c66affSColin Finck {
586*c2c66affSColin Finck     This->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
587*c2c66affSColin Finck     This->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
588*c2c66affSColin Finck     This->IHttpNegotiate2_iface.lpVtbl = &HttpNegotiate2Vtbl;
589*c2c66affSColin Finck     This->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
590*c2c66affSColin Finck     This->vtbl = vtbl;
591*c2c66affSColin Finck     This->ref = 1;
592*c2c66affSColin Finck     This->bindf = bindf;
593*c2c66affSColin Finck     This->bom = BOM_NONE;
594*c2c66affSColin Finck 
595*c2c66affSColin Finck     list_init(&This->entry);
596*c2c66affSColin Finck 
597*c2c66affSColin Finck     if(mon)
598*c2c66affSColin Finck         IMoniker_AddRef(mon);
599*c2c66affSColin Finck     This->mon = mon;
600*c2c66affSColin Finck }
601*c2c66affSColin Finck 
read_stream(BSCallback * This,IStream * stream,void * buf,DWORD size,DWORD * ret_size)602*c2c66affSColin Finck HRESULT read_stream(BSCallback *This, IStream *stream, void *buf, DWORD size, DWORD *ret_size)
603*c2c66affSColin Finck {
604*c2c66affSColin Finck     DWORD read_size = 0, skip=0;
605*c2c66affSColin Finck     BYTE *data = buf;
606*c2c66affSColin Finck     HRESULT hres;
607*c2c66affSColin Finck 
608*c2c66affSColin Finck     hres = IStream_Read(stream, buf, size, &read_size);
609*c2c66affSColin Finck 
610*c2c66affSColin Finck     if(!This->readed && This->bom == BOM_NONE) {
611*c2c66affSColin Finck         if(read_size >= 2 && data[0] == 0xff && data[1] == 0xfe) {
612*c2c66affSColin Finck             This->bom = BOM_UTF16;
613*c2c66affSColin Finck             skip = 2;
614*c2c66affSColin Finck         }else if(read_size >= 3 && data[0] == 0xef && data[1] == 0xbb && data[2] == 0xbf) {
615*c2c66affSColin Finck             This->bom = BOM_UTF8;
616*c2c66affSColin Finck             skip = 3;
617*c2c66affSColin Finck         }
618*c2c66affSColin Finck         if(skip) {
619*c2c66affSColin Finck             read_size -= skip;
620*c2c66affSColin Finck             if(read_size)
621*c2c66affSColin Finck                 memmove(data, data+skip, read_size);
622*c2c66affSColin Finck         }
623*c2c66affSColin Finck     }
624*c2c66affSColin Finck 
625*c2c66affSColin Finck     This->readed += read_size;
626*c2c66affSColin Finck     *ret_size = read_size;
627*c2c66affSColin Finck     return hres;
628*c2c66affSColin Finck }
629*c2c66affSColin Finck 
parse_content_type(nsChannelBSC * This,const WCHAR * value)630*c2c66affSColin Finck static void parse_content_type(nsChannelBSC *This, const WCHAR *value)
631*c2c66affSColin Finck {
632*c2c66affSColin Finck     const WCHAR *ptr;
633*c2c66affSColin Finck     size_t len;
634*c2c66affSColin Finck 
635*c2c66affSColin Finck     static const WCHAR charsetW[] = {'c','h','a','r','s','e','t','='};
636*c2c66affSColin Finck 
637*c2c66affSColin Finck     ptr = strchrW(value, ';');
638*c2c66affSColin Finck     if(!ptr)
639*c2c66affSColin Finck         return;
640*c2c66affSColin Finck 
641*c2c66affSColin Finck     ptr++;
642*c2c66affSColin Finck     while(*ptr && isspaceW(*ptr))
643*c2c66affSColin Finck         ptr++;
644*c2c66affSColin Finck 
645*c2c66affSColin Finck     len = strlenW(value);
646*c2c66affSColin Finck     if(ptr + sizeof(charsetW)/sizeof(WCHAR) < value+len && !memicmpW(ptr, charsetW, sizeof(charsetW)/sizeof(WCHAR))) {
647*c2c66affSColin Finck         size_t charset_len, lena;
648*c2c66affSColin Finck         nsACString charset_str;
649*c2c66affSColin Finck         const WCHAR *charset;
650*c2c66affSColin Finck         char *charseta;
651*c2c66affSColin Finck 
652*c2c66affSColin Finck         ptr += sizeof(charsetW)/sizeof(WCHAR);
653*c2c66affSColin Finck 
654*c2c66affSColin Finck         if(*ptr == '\'') {
655*c2c66affSColin Finck             FIXME("Quoted value\n");
656*c2c66affSColin Finck             return;
657*c2c66affSColin Finck         }else {
658*c2c66affSColin Finck             charset = ptr;
659*c2c66affSColin Finck             while(*ptr && *ptr != ',')
660*c2c66affSColin Finck                 ptr++;
661*c2c66affSColin Finck             charset_len = ptr-charset;
662*c2c66affSColin Finck         }
663*c2c66affSColin Finck 
664*c2c66affSColin Finck         lena = WideCharToMultiByte(CP_ACP, 0, charset, charset_len, NULL, 0, NULL, NULL);
665*c2c66affSColin Finck         charseta = heap_alloc(lena+1);
666*c2c66affSColin Finck         if(!charseta)
667*c2c66affSColin Finck             return;
668*c2c66affSColin Finck 
669*c2c66affSColin Finck         WideCharToMultiByte(CP_ACP, 0, charset, charset_len, charseta, lena, NULL, NULL);
670*c2c66affSColin Finck         charseta[lena] = 0;
671*c2c66affSColin Finck 
672*c2c66affSColin Finck         nsACString_InitDepend(&charset_str, charseta);
673*c2c66affSColin Finck         nsIHttpChannel_SetContentCharset(&This->nschannel->nsIHttpChannel_iface, &charset_str);
674*c2c66affSColin Finck         nsACString_Finish(&charset_str);
675*c2c66affSColin Finck         heap_free(charseta);
676*c2c66affSColin Finck     }else {
677*c2c66affSColin Finck         FIXME("unhandled: %s\n", debugstr_wn(ptr, len - (ptr-value)));
678*c2c66affSColin Finck     }
679*c2c66affSColin Finck }
680*c2c66affSColin Finck 
parse_headers(const WCHAR * headers,struct list * headers_list)681*c2c66affSColin Finck static HRESULT parse_headers(const WCHAR *headers, struct list *headers_list)
682*c2c66affSColin Finck {
683*c2c66affSColin Finck     const WCHAR *header, *header_end, *colon, *value;
684*c2c66affSColin Finck     HRESULT hres;
685*c2c66affSColin Finck 
686*c2c66affSColin Finck     header = headers;
687*c2c66affSColin Finck     while(*header) {
688*c2c66affSColin Finck         if(header[0] == '\r' && header[1] == '\n' && !header[2])
689*c2c66affSColin Finck             break;
690*c2c66affSColin Finck         for(colon = header; *colon && *colon != ':' && *colon != '\r'; colon++);
691*c2c66affSColin Finck         if(*colon != ':')
692*c2c66affSColin Finck             return E_FAIL;
693*c2c66affSColin Finck 
694*c2c66affSColin Finck         value = colon+1;
695*c2c66affSColin Finck         while(*value == ' ')
696*c2c66affSColin Finck             value++;
697*c2c66affSColin Finck         if(!*value)
698*c2c66affSColin Finck             return E_FAIL;
699*c2c66affSColin Finck 
700*c2c66affSColin Finck         for(header_end = value+1; *header_end && *header_end != '\r'; header_end++);
701*c2c66affSColin Finck 
702*c2c66affSColin Finck         hres = set_http_header(headers_list, header, colon-header, value, header_end-value);
703*c2c66affSColin Finck         if(FAILED(hres))
704*c2c66affSColin Finck             return hres;
705*c2c66affSColin Finck 
706*c2c66affSColin Finck         header = header_end;
707*c2c66affSColin Finck         if(header[0] == '\r' && header[1] == '\n')
708*c2c66affSColin Finck             header += 2;
709*c2c66affSColin Finck     }
710*c2c66affSColin Finck 
711*c2c66affSColin Finck     return S_OK;
712*c2c66affSColin Finck }
713*c2c66affSColin Finck 
process_response_headers(nsChannelBSC * This,const WCHAR * headers)714*c2c66affSColin Finck static HRESULT process_response_headers(nsChannelBSC *This, const WCHAR *headers)
715*c2c66affSColin Finck {
716*c2c66affSColin Finck     http_header_t *iter;
717*c2c66affSColin Finck     HRESULT hres;
718*c2c66affSColin Finck 
719*c2c66affSColin Finck     static const WCHAR content_typeW[] = {'c','o','n','t','e','n','t','-','t','y','p','e',0};
720*c2c66affSColin Finck 
721*c2c66affSColin Finck     hres = parse_headers(headers, &This->nschannel->response_headers);
722*c2c66affSColin Finck     if(FAILED(hres))
723*c2c66affSColin Finck         return hres;
724*c2c66affSColin Finck 
725*c2c66affSColin Finck     LIST_FOR_EACH_ENTRY(iter, &This->nschannel->response_headers, http_header_t, entry) {
726*c2c66affSColin Finck         if(!strcmpiW(iter->header, content_typeW))
727*c2c66affSColin Finck             parse_content_type(This, iter->data);
728*c2c66affSColin Finck     }
729*c2c66affSColin Finck 
730*c2c66affSColin Finck     return S_OK;
731*c2c66affSColin Finck }
732*c2c66affSColin Finck 
query_http_info(nsChannelBSC * This,IWinInetHttpInfo * wininet_info)733*c2c66affSColin Finck static void query_http_info(nsChannelBSC *This, IWinInetHttpInfo *wininet_info)
734*c2c66affSColin Finck {
735*c2c66affSColin Finck     const WCHAR *ptr;
736*c2c66affSColin Finck     DWORD len = 0;
737*c2c66affSColin Finck     WCHAR *buf;
738*c2c66affSColin Finck 
739*c2c66affSColin Finck     IWinInetHttpInfo_QueryInfo(wininet_info, HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &len, NULL, NULL);
740*c2c66affSColin Finck     if(!len)
741*c2c66affSColin Finck         return;
742*c2c66affSColin Finck 
743*c2c66affSColin Finck     buf = heap_alloc(len);
744*c2c66affSColin Finck     if(!buf)
745*c2c66affSColin Finck         return;
746*c2c66affSColin Finck 
747*c2c66affSColin Finck     IWinInetHttpInfo_QueryInfo(wininet_info, HTTP_QUERY_RAW_HEADERS_CRLF, buf, &len, NULL, NULL);
748*c2c66affSColin Finck     if(!len) {
749*c2c66affSColin Finck         heap_free(buf);
750*c2c66affSColin Finck         return;
751*c2c66affSColin Finck     }
752*c2c66affSColin Finck 
753*c2c66affSColin Finck     ptr = strchrW(buf, '\r');
754*c2c66affSColin Finck     if(ptr && ptr[1] == '\n') {
755*c2c66affSColin Finck         ptr += 2;
756*c2c66affSColin Finck         process_response_headers(This, ptr);
757*c2c66affSColin Finck     }
758*c2c66affSColin Finck 
759*c2c66affSColin Finck     heap_free(buf);
760*c2c66affSColin Finck }
761*c2c66affSColin Finck 
start_binding(HTMLInnerWindow * inner_window,BSCallback * bscallback,IBindCtx * bctx)762*c2c66affSColin Finck HRESULT start_binding(HTMLInnerWindow *inner_window, BSCallback *bscallback, IBindCtx *bctx)
763*c2c66affSColin Finck {
764*c2c66affSColin Finck     IStream *str = NULL;
765*c2c66affSColin Finck     HRESULT hres;
766*c2c66affSColin Finck 
767*c2c66affSColin Finck     TRACE("(%p %p %p)\n", inner_window, bscallback, bctx);
768*c2c66affSColin Finck 
769*c2c66affSColin Finck     bscallback->window = inner_window;
770*c2c66affSColin Finck 
771*c2c66affSColin Finck     /* NOTE: IE7 calls IsSystemMoniker here*/
772*c2c66affSColin Finck 
773*c2c66affSColin Finck     if(bctx) {
774*c2c66affSColin Finck         hres = RegisterBindStatusCallback(bctx, &bscallback->IBindStatusCallback_iface, NULL, 0);
775*c2c66affSColin Finck         if(SUCCEEDED(hres))
776*c2c66affSColin Finck             IBindCtx_AddRef(bctx);
777*c2c66affSColin Finck     }else {
778*c2c66affSColin Finck         hres = CreateAsyncBindCtx(0, &bscallback->IBindStatusCallback_iface, NULL, &bctx);
779*c2c66affSColin Finck     }
780*c2c66affSColin Finck 
781*c2c66affSColin Finck     if(FAILED(hres)) {
782*c2c66affSColin Finck         bscallback->window = NULL;
783*c2c66affSColin Finck         return hres;
784*c2c66affSColin Finck     }
785*c2c66affSColin Finck 
786*c2c66affSColin Finck     hres = IMoniker_BindToStorage(bscallback->mon, bctx, NULL, &IID_IStream, (void**)&str);
787*c2c66affSColin Finck     IBindCtx_Release(bctx);
788*c2c66affSColin Finck     if(FAILED(hres)) {
789*c2c66affSColin Finck         WARN("BindToStorage failed: %08x\n", hres);
790*c2c66affSColin Finck         bscallback->window = NULL;
791*c2c66affSColin Finck         return hres;
792*c2c66affSColin Finck     }
793*c2c66affSColin Finck 
794*c2c66affSColin Finck     if(str)
795*c2c66affSColin Finck         IStream_Release(str);
796*c2c66affSColin Finck 
797*c2c66affSColin Finck     return S_OK;
798*c2c66affSColin Finck }
799*c2c66affSColin Finck 
read_post_data_stream(nsIInputStream * stream,BOOL contains_headers,struct list * headers_list,request_data_t * request_data)800*c2c66affSColin Finck static HRESULT read_post_data_stream(nsIInputStream *stream, BOOL contains_headers, struct list *headers_list,
801*c2c66affSColin Finck         request_data_t *request_data)
802*c2c66affSColin Finck {
803*c2c66affSColin Finck     nsISeekableStream *seekable_stream;
804*c2c66affSColin Finck     UINT64 available = 0;
805*c2c66affSColin Finck     UINT32 data_len = 0;
806*c2c66affSColin Finck     char *data, *post_data;
807*c2c66affSColin Finck     nsresult nsres;
808*c2c66affSColin Finck     HRESULT hres = S_OK;
809*c2c66affSColin Finck 
810*c2c66affSColin Finck     if(!stream)
811*c2c66affSColin Finck         return S_OK;
812*c2c66affSColin Finck 
813*c2c66affSColin Finck     nsres =  nsIInputStream_Available(stream, &available);
814*c2c66affSColin Finck     if(NS_FAILED(nsres))
815*c2c66affSColin Finck         return E_FAIL;
816*c2c66affSColin Finck 
817*c2c66affSColin Finck     post_data = data = GlobalAlloc(0, available+1);
818*c2c66affSColin Finck     if(!data)
819*c2c66affSColin Finck         return E_OUTOFMEMORY;
820*c2c66affSColin Finck 
821*c2c66affSColin Finck     nsres = nsIInputStream_Read(stream, data, available, &data_len);
822*c2c66affSColin Finck     if(NS_FAILED(nsres)) {
823*c2c66affSColin Finck         GlobalFree(data);
824*c2c66affSColin Finck         return E_FAIL;
825*c2c66affSColin Finck     }
826*c2c66affSColin Finck 
827*c2c66affSColin Finck     if(contains_headers) {
828*c2c66affSColin Finck         if(data_len >= 2 && data[0] == '\r' && data[1] == '\n') {
829*c2c66affSColin Finck             post_data = data+2;
830*c2c66affSColin Finck             data_len -= 2;
831*c2c66affSColin Finck         }else {
832*c2c66affSColin Finck             WCHAR *headers;
833*c2c66affSColin Finck             DWORD size;
834*c2c66affSColin Finck             char *ptr;
835*c2c66affSColin Finck 
836*c2c66affSColin Finck             post_data += data_len;
837*c2c66affSColin Finck             for(ptr = data; ptr+4 < data+data_len; ptr++) {
838*c2c66affSColin Finck                 if(!memcmp(ptr, "\r\n\r\n", 4)) {
839*c2c66affSColin Finck                     ptr += 2;
840*c2c66affSColin Finck                     post_data = ptr+2;
841*c2c66affSColin Finck                     break;
842*c2c66affSColin Finck                 }
843*c2c66affSColin Finck             }
844*c2c66affSColin Finck 
845*c2c66affSColin Finck             data_len -= post_data-data;
846*c2c66affSColin Finck 
847*c2c66affSColin Finck             size = MultiByteToWideChar(CP_ACP, 0, data, ptr-data, NULL, 0);
848*c2c66affSColin Finck             headers = heap_alloc((size+1)*sizeof(WCHAR));
849*c2c66affSColin Finck             if(headers) {
850*c2c66affSColin Finck                 MultiByteToWideChar(CP_ACP, 0, data, ptr-data, headers, size);
851*c2c66affSColin Finck                 headers[size] = 0;
852*c2c66affSColin Finck                 if(headers_list)
853*c2c66affSColin Finck                     hres = parse_headers(headers, headers_list);
854*c2c66affSColin Finck                 if(SUCCEEDED(hres))
855*c2c66affSColin Finck                     request_data->headers = headers;
856*c2c66affSColin Finck                 else
857*c2c66affSColin Finck                     heap_free(headers);
858*c2c66affSColin Finck             }else {
859*c2c66affSColin Finck                 hres = E_OUTOFMEMORY;
860*c2c66affSColin Finck             }
861*c2c66affSColin Finck         }
862*c2c66affSColin Finck     }
863*c2c66affSColin Finck 
864*c2c66affSColin Finck     if(FAILED(hres)) {
865*c2c66affSColin Finck         GlobalFree(data);
866*c2c66affSColin Finck         return hres;
867*c2c66affSColin Finck     }
868*c2c66affSColin Finck 
869*c2c66affSColin Finck     if(!data_len) {
870*c2c66affSColin Finck         GlobalFree(data);
871*c2c66affSColin Finck         post_data = NULL;
872*c2c66affSColin Finck     }else if(post_data != data) {
873*c2c66affSColin Finck         char *new_data;
874*c2c66affSColin Finck 
875*c2c66affSColin Finck         new_data = GlobalAlloc(0, data_len+1);
876*c2c66affSColin Finck         if(new_data)
877*c2c66affSColin Finck             memcpy(new_data, post_data, data_len);
878*c2c66affSColin Finck         GlobalFree(data);
879*c2c66affSColin Finck         if(!new_data)
880*c2c66affSColin Finck             return E_OUTOFMEMORY;
881*c2c66affSColin Finck         post_data = new_data;
882*c2c66affSColin Finck     }
883*c2c66affSColin Finck 
884*c2c66affSColin Finck     if(post_data)
885*c2c66affSColin Finck         post_data[data_len] = 0;
886*c2c66affSColin Finck     request_data->post_data = post_data;
887*c2c66affSColin Finck     request_data->post_data_len = data_len;
888*c2c66affSColin Finck 
889*c2c66affSColin Finck     nsres = nsIInputStream_QueryInterface(stream, &IID_nsISeekableStream, (void**)&seekable_stream);
890*c2c66affSColin Finck     assert(nsres == NS_OK);
891*c2c66affSColin Finck 
892*c2c66affSColin Finck     nsres = nsISeekableStream_Seek(seekable_stream, NS_SEEK_SET, 0);
893*c2c66affSColin Finck     assert(nsres == NS_OK);
894*c2c66affSColin Finck 
895*c2c66affSColin Finck     nsISeekableStream_Release(seekable_stream);
896*c2c66affSColin Finck 
897*c2c66affSColin Finck     nsIInputStream_AddRef(stream);
898*c2c66affSColin Finck     request_data->post_stream = stream;
899*c2c66affSColin Finck     TRACE("post_data = %s\n", debugstr_an(request_data->post_data, request_data->post_data_len));
900*c2c66affSColin Finck     return S_OK;
901*c2c66affSColin Finck }
902*c2c66affSColin Finck 
on_start_nsrequest(nsChannelBSC * This)903*c2c66affSColin Finck static HRESULT on_start_nsrequest(nsChannelBSC *This)
904*c2c66affSColin Finck {
905*c2c66affSColin Finck     nsresult nsres;
906*c2c66affSColin Finck 
907*c2c66affSColin Finck     /* FIXME: it's needed for http connections from BindToObject. */
908*c2c66affSColin Finck     if(!This->nschannel->response_status)
909*c2c66affSColin Finck         This->nschannel->response_status = 200;
910*c2c66affSColin Finck 
911*c2c66affSColin Finck     nsres = nsIStreamListener_OnStartRequest(This->nslistener,
912*c2c66affSColin Finck             (nsIRequest*)&This->nschannel->nsIHttpChannel_iface, This->nscontext);
913*c2c66affSColin Finck     if(NS_FAILED(nsres)) {
914*c2c66affSColin Finck         FIXME("OnStartRequest failed: %08x\n", nsres);
915*c2c66affSColin Finck         return E_FAIL;
916*c2c66affSColin Finck     }
917*c2c66affSColin Finck 
918*c2c66affSColin Finck     if(This->is_doc_channel) {
919*c2c66affSColin Finck         if(!This->bsc.window)
920*c2c66affSColin Finck             return E_ABORT; /* Binding aborted in OnStartRequest call. */
921*c2c66affSColin Finck         update_window_doc(This->bsc.window);
922*c2c66affSColin Finck         if(This->bsc.window->base.outer_window->readystate != READYSTATE_LOADING)
923*c2c66affSColin Finck             set_ready_state(This->bsc.window->base.outer_window, READYSTATE_LOADING);
924*c2c66affSColin Finck     }
925*c2c66affSColin Finck 
926*c2c66affSColin Finck     return S_OK;
927*c2c66affSColin Finck }
928*c2c66affSColin Finck 
on_stop_nsrequest(nsChannelBSC * This,HRESULT result)929*c2c66affSColin Finck static void on_stop_nsrequest(nsChannelBSC *This, HRESULT result)
930*c2c66affSColin Finck {
931*c2c66affSColin Finck     nsresult nsres, request_result;
932*c2c66affSColin Finck 
933*c2c66affSColin Finck     switch(result) {
934*c2c66affSColin Finck     case S_OK:
935*c2c66affSColin Finck         request_result = NS_OK;
936*c2c66affSColin Finck         break;
937*c2c66affSColin Finck     case E_ABORT:
938*c2c66affSColin Finck         request_result = NS_BINDING_ABORTED;
939*c2c66affSColin Finck         break;
940*c2c66affSColin Finck     default:
941*c2c66affSColin Finck         request_result = NS_ERROR_FAILURE;
942*c2c66affSColin Finck     }
943*c2c66affSColin Finck 
944*c2c66affSColin Finck     if(This->nslistener) {
945*c2c66affSColin Finck         nsres = nsIStreamListener_OnStopRequest(This->nslistener,
946*c2c66affSColin Finck                  (nsIRequest*)&This->nschannel->nsIHttpChannel_iface, This->nscontext,
947*c2c66affSColin Finck                  request_result);
948*c2c66affSColin Finck         if(NS_FAILED(nsres))
949*c2c66affSColin Finck             WARN("OnStopRequest failed: %08x\n", nsres);
950*c2c66affSColin Finck     }
951*c2c66affSColin Finck 
952*c2c66affSColin Finck     if(This->nschannel && This->nschannel->load_group) {
953*c2c66affSColin Finck         nsres = nsILoadGroup_RemoveRequest(This->nschannel->load_group,
954*c2c66affSColin Finck                 (nsIRequest*)&This->nschannel->nsIHttpChannel_iface, NULL, request_result);
955*c2c66affSColin Finck         if(NS_FAILED(nsres))
956*c2c66affSColin Finck             ERR("RemoveRequest failed: %08x\n", nsres);
957*c2c66affSColin Finck     }
958*c2c66affSColin Finck }
959*c2c66affSColin Finck 
read_stream_data(nsChannelBSC * This,IStream * stream)960*c2c66affSColin Finck static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream)
961*c2c66affSColin Finck {
962*c2c66affSColin Finck     DWORD read;
963*c2c66affSColin Finck     nsresult nsres;
964*c2c66affSColin Finck     HRESULT hres;
965*c2c66affSColin Finck 
966*c2c66affSColin Finck     if(!This->response_processed) {
967*c2c66affSColin Finck         IWinInetHttpInfo *wininet_info;
968*c2c66affSColin Finck 
969*c2c66affSColin Finck         This->response_processed = TRUE;
970*c2c66affSColin Finck         if(This->bsc.binding) {
971*c2c66affSColin Finck             hres = IBinding_QueryInterface(This->bsc.binding, &IID_IWinInetHttpInfo, (void**)&wininet_info);
972*c2c66affSColin Finck             if(SUCCEEDED(hres)) {
973*c2c66affSColin Finck                 query_http_info(This, wininet_info);
974*c2c66affSColin Finck                 IWinInetHttpInfo_Release(wininet_info);
975*c2c66affSColin Finck             }
976*c2c66affSColin Finck         }
977*c2c66affSColin Finck     }
978*c2c66affSColin Finck 
979*c2c66affSColin Finck     if(!This->nschannel)
980*c2c66affSColin Finck         return S_OK;
981*c2c66affSColin Finck 
982*c2c66affSColin Finck     if(!This->nslistener) {
983*c2c66affSColin Finck         BYTE buf[1024];
984*c2c66affSColin Finck 
985*c2c66affSColin Finck         do {
986*c2c66affSColin Finck             hres = read_stream(&This->bsc, stream, buf, sizeof(buf), &read);
987*c2c66affSColin Finck         }while(hres == S_OK && read);
988*c2c66affSColin Finck 
989*c2c66affSColin Finck         return S_OK;
990*c2c66affSColin Finck     }
991*c2c66affSColin Finck 
992*c2c66affSColin Finck     if(!This->nsstream) {
993*c2c66affSColin Finck         This->nsstream = create_nsprotocol_stream();
994*c2c66affSColin Finck         if(!This->nsstream)
995*c2c66affSColin Finck             return E_OUTOFMEMORY;
996*c2c66affSColin Finck     }
997*c2c66affSColin Finck 
998*c2c66affSColin Finck     do {
999*c2c66affSColin Finck         BOOL first_read = !This->bsc.readed;
1000*c2c66affSColin Finck 
1001*c2c66affSColin Finck         hres = read_stream(&This->bsc, stream, This->nsstream->buf+This->nsstream->buf_size,
1002*c2c66affSColin Finck                 sizeof(This->nsstream->buf)-This->nsstream->buf_size, &read);
1003*c2c66affSColin Finck         if(!read)
1004*c2c66affSColin Finck             break;
1005*c2c66affSColin Finck 
1006*c2c66affSColin Finck         This->nsstream->buf_size += read;
1007*c2c66affSColin Finck 
1008*c2c66affSColin Finck         if(first_read) {
1009*c2c66affSColin Finck             switch(This->bsc.bom) {
1010*c2c66affSColin Finck             case BOM_UTF8:
1011*c2c66affSColin Finck                 This->nschannel->charset = heap_strdupA(UTF8_STR);
1012*c2c66affSColin Finck                 break;
1013*c2c66affSColin Finck             case BOM_UTF16:
1014*c2c66affSColin Finck                 This->nschannel->charset = heap_strdupA(UTF16_STR);
1015*c2c66affSColin Finck             case BOM_NONE:
1016*c2c66affSColin Finck                 /* FIXME: Get charset from HTTP headers */;
1017*c2c66affSColin Finck             }
1018*c2c66affSColin Finck 
1019*c2c66affSColin Finck             if(!This->nschannel->content_type) {
1020*c2c66affSColin Finck                 WCHAR *mime;
1021*c2c66affSColin Finck 
1022*c2c66affSColin Finck                 hres = FindMimeFromData(NULL, NULL, This->nsstream->buf, This->nsstream->buf_size,
1023*c2c66affSColin Finck                         This->is_doc_channel ? text_htmlW : NULL, 0, &mime, 0);
1024*c2c66affSColin Finck                 if(FAILED(hres))
1025*c2c66affSColin Finck                     return hres;
1026*c2c66affSColin Finck 
1027*c2c66affSColin Finck                 TRACE("Found MIME %s\n", debugstr_w(mime));
1028*c2c66affSColin Finck 
1029*c2c66affSColin Finck                 This->nschannel->content_type = heap_strdupWtoA(mime);
1030*c2c66affSColin Finck                 CoTaskMemFree(mime);
1031*c2c66affSColin Finck                 if(!This->nschannel->content_type)
1032*c2c66affSColin Finck                     return E_OUTOFMEMORY;
1033*c2c66affSColin Finck             }
1034*c2c66affSColin Finck 
1035*c2c66affSColin Finck             hres = on_start_nsrequest(This);
1036*c2c66affSColin Finck             if(FAILED(hres))
1037*c2c66affSColin Finck                 return hres;
1038*c2c66affSColin Finck         }
1039*c2c66affSColin Finck 
1040*c2c66affSColin Finck         nsres = nsIStreamListener_OnDataAvailable(This->nslistener,
1041*c2c66affSColin Finck                 (nsIRequest*)&This->nschannel->nsIHttpChannel_iface, This->nscontext,
1042*c2c66affSColin Finck                 &This->nsstream->nsIInputStream_iface, This->bsc.readed-This->nsstream->buf_size,
1043*c2c66affSColin Finck                 This->nsstream->buf_size);
1044*c2c66affSColin Finck         if(NS_FAILED(nsres))
1045*c2c66affSColin Finck             ERR("OnDataAvailable failed: %08x\n", nsres);
1046*c2c66affSColin Finck 
1047*c2c66affSColin Finck         if(This->nsstream->buf_size == sizeof(This->nsstream->buf)) {
1048*c2c66affSColin Finck             ERR("buffer is full\n");
1049*c2c66affSColin Finck             break;
1050*c2c66affSColin Finck         }
1051*c2c66affSColin Finck     }while(hres == S_OK);
1052*c2c66affSColin Finck 
1053*c2c66affSColin Finck     return S_OK;
1054*c2c66affSColin Finck }
1055*c2c66affSColin Finck 
1056*c2c66affSColin Finck typedef struct {
1057*c2c66affSColin Finck     nsIAsyncVerifyRedirectCallback nsIAsyncVerifyRedirectCallback_iface;
1058*c2c66affSColin Finck 
1059*c2c66affSColin Finck     LONG ref;
1060*c2c66affSColin Finck 
1061*c2c66affSColin Finck     nsChannel *nschannel;
1062*c2c66affSColin Finck     nsChannelBSC *bsc;
1063*c2c66affSColin Finck } nsRedirectCallback;
1064*c2c66affSColin Finck 
impl_from_nsIAsyncVerifyRedirectCallback(nsIAsyncVerifyRedirectCallback * iface)1065*c2c66affSColin Finck static nsRedirectCallback *impl_from_nsIAsyncVerifyRedirectCallback(nsIAsyncVerifyRedirectCallback *iface)
1066*c2c66affSColin Finck {
1067*c2c66affSColin Finck     return CONTAINING_RECORD(iface, nsRedirectCallback, nsIAsyncVerifyRedirectCallback_iface);
1068*c2c66affSColin Finck }
1069*c2c66affSColin Finck 
nsAsyncVerifyRedirectCallback_QueryInterface(nsIAsyncVerifyRedirectCallback * iface,nsIIDRef riid,void ** result)1070*c2c66affSColin Finck static nsresult NSAPI nsAsyncVerifyRedirectCallback_QueryInterface(nsIAsyncVerifyRedirectCallback *iface,
1071*c2c66affSColin Finck         nsIIDRef riid, void **result)
1072*c2c66affSColin Finck {
1073*c2c66affSColin Finck     nsRedirectCallback *This = impl_from_nsIAsyncVerifyRedirectCallback(iface);
1074*c2c66affSColin Finck 
1075*c2c66affSColin Finck     if(IsEqualGUID(&IID_nsISupports, riid)) {
1076*c2c66affSColin Finck         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1077*c2c66affSColin Finck         *result = &This->nsIAsyncVerifyRedirectCallback_iface;
1078*c2c66affSColin Finck     }else if(IsEqualGUID(&IID_nsIAsyncVerifyRedirectCallback, riid)) {
1079*c2c66affSColin Finck         TRACE("(%p)->(IID_nsIAsyncVerifyRedirectCallback %p)\n", This, result);
1080*c2c66affSColin Finck         *result = &This->nsIAsyncVerifyRedirectCallback_iface;
1081*c2c66affSColin Finck     }else {
1082*c2c66affSColin Finck         *result = NULL;
1083*c2c66affSColin Finck         WARN("unimplemented iface %s\n", debugstr_guid(riid));
1084*c2c66affSColin Finck         return NS_NOINTERFACE;
1085*c2c66affSColin Finck     }
1086*c2c66affSColin Finck 
1087*c2c66affSColin Finck     nsISupports_AddRef((nsISupports*)*result);
1088*c2c66affSColin Finck     return NS_OK;
1089*c2c66affSColin Finck }
1090*c2c66affSColin Finck 
nsAsyncVerifyRedirectCallback_AddRef(nsIAsyncVerifyRedirectCallback * iface)1091*c2c66affSColin Finck static nsrefcnt NSAPI nsAsyncVerifyRedirectCallback_AddRef(nsIAsyncVerifyRedirectCallback *iface)
1092*c2c66affSColin Finck {
1093*c2c66affSColin Finck     nsRedirectCallback *This = impl_from_nsIAsyncVerifyRedirectCallback(iface);
1094*c2c66affSColin Finck     LONG ref = InterlockedIncrement(&This->ref);
1095*c2c66affSColin Finck 
1096*c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
1097*c2c66affSColin Finck 
1098*c2c66affSColin Finck     return ref;
1099*c2c66affSColin Finck }
1100*c2c66affSColin Finck 
nsAsyncVerifyRedirectCallback_Release(nsIAsyncVerifyRedirectCallback * iface)1101*c2c66affSColin Finck static nsrefcnt NSAPI nsAsyncVerifyRedirectCallback_Release(nsIAsyncVerifyRedirectCallback *iface)
1102*c2c66affSColin Finck {
1103*c2c66affSColin Finck     nsRedirectCallback *This = impl_from_nsIAsyncVerifyRedirectCallback(iface);
1104*c2c66affSColin Finck     LONG ref = InterlockedDecrement(&This->ref);
1105*c2c66affSColin Finck 
1106*c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
1107*c2c66affSColin Finck 
1108*c2c66affSColin Finck     if(!ref) {
1109*c2c66affSColin Finck         IBindStatusCallback_Release(&This->bsc->bsc.IBindStatusCallback_iface);
1110*c2c66affSColin Finck         nsIHttpChannel_Release(&This->nschannel->nsIHttpChannel_iface);
1111*c2c66affSColin Finck         heap_free(This);
1112*c2c66affSColin Finck     }
1113*c2c66affSColin Finck 
1114*c2c66affSColin Finck     return ref;
1115*c2c66affSColin Finck }
1116*c2c66affSColin Finck 
nsAsyncVerifyRedirectCallback_OnRedirectVerifyCallback(nsIAsyncVerifyRedirectCallback * iface,nsresult result)1117*c2c66affSColin Finck static nsresult NSAPI nsAsyncVerifyRedirectCallback_OnRedirectVerifyCallback(nsIAsyncVerifyRedirectCallback *iface, nsresult result)
1118*c2c66affSColin Finck {
1119*c2c66affSColin Finck     nsRedirectCallback *This = impl_from_nsIAsyncVerifyRedirectCallback(iface);
1120*c2c66affSColin Finck     nsChannel *old_nschannel;
1121*c2c66affSColin Finck     nsresult nsres;
1122*c2c66affSColin Finck 
1123*c2c66affSColin Finck     TRACE("(%p)->(%08x)\n", This, result);
1124*c2c66affSColin Finck 
1125*c2c66affSColin Finck     old_nschannel = This->bsc->nschannel;
1126*c2c66affSColin Finck     nsIHttpChannel_AddRef(&This->nschannel->nsIHttpChannel_iface);
1127*c2c66affSColin Finck     This->bsc->nschannel = This->nschannel;
1128*c2c66affSColin Finck 
1129*c2c66affSColin Finck     if(This->nschannel->load_group) {
1130*c2c66affSColin Finck         nsres = nsILoadGroup_AddRequest(This->nschannel->load_group, (nsIRequest*)&This->nschannel->nsIHttpChannel_iface,
1131*c2c66affSColin Finck                 NULL);
1132*c2c66affSColin Finck         if(NS_FAILED(nsres))
1133*c2c66affSColin Finck             ERR("AddRequest failed: %08x\n", nsres);
1134*c2c66affSColin Finck     }
1135*c2c66affSColin Finck 
1136*c2c66affSColin Finck     if(This->bsc->is_doc_channel) {
1137*c2c66affSColin Finck         IUri *uri = nsuri_get_uri(This->nschannel->uri);
1138*c2c66affSColin Finck 
1139*c2c66affSColin Finck         if(uri) {
1140*c2c66affSColin Finck             set_current_uri(This->bsc->bsc.window->base.outer_window, uri);
1141*c2c66affSColin Finck             IUri_Release(uri);
1142*c2c66affSColin Finck         }else {
1143*c2c66affSColin Finck             WARN("Could not get IUri from nsWineURI\n");
1144*c2c66affSColin Finck         }
1145*c2c66affSColin Finck     }
1146*c2c66affSColin Finck 
1147*c2c66affSColin Finck     if(old_nschannel) {
1148*c2c66affSColin Finck         if(old_nschannel->load_group) {
1149*c2c66affSColin Finck             nsres = nsILoadGroup_RemoveRequest(old_nschannel->load_group,
1150*c2c66affSColin Finck                     (nsIRequest*)&old_nschannel->nsIHttpChannel_iface, NULL, NS_OK);
1151*c2c66affSColin Finck             if(NS_FAILED(nsres))
1152*c2c66affSColin Finck                 ERR("RemoveRequest failed: %08x\n", nsres);
1153*c2c66affSColin Finck         }
1154*c2c66affSColin Finck         nsIHttpChannel_Release(&old_nschannel->nsIHttpChannel_iface);
1155*c2c66affSColin Finck     }
1156*c2c66affSColin Finck 
1157*c2c66affSColin Finck     return NS_OK;
1158*c2c66affSColin Finck }
1159*c2c66affSColin Finck 
1160*c2c66affSColin Finck static const nsIAsyncVerifyRedirectCallbackVtbl nsAsyncVerifyRedirectCallbackVtbl = {
1161*c2c66affSColin Finck     nsAsyncVerifyRedirectCallback_QueryInterface,
1162*c2c66affSColin Finck     nsAsyncVerifyRedirectCallback_AddRef,
1163*c2c66affSColin Finck     nsAsyncVerifyRedirectCallback_Release,
1164*c2c66affSColin Finck     nsAsyncVerifyRedirectCallback_OnRedirectVerifyCallback
1165*c2c66affSColin Finck };
1166*c2c66affSColin Finck 
create_redirect_callback(nsChannel * nschannel,nsChannelBSC * bsc,nsRedirectCallback ** ret)1167*c2c66affSColin Finck static HRESULT create_redirect_callback(nsChannel *nschannel, nsChannelBSC *bsc, nsRedirectCallback **ret)
1168*c2c66affSColin Finck {
1169*c2c66affSColin Finck     nsRedirectCallback *callback;
1170*c2c66affSColin Finck 
1171*c2c66affSColin Finck     callback = heap_alloc(sizeof(*callback));
1172*c2c66affSColin Finck     if(!callback)
1173*c2c66affSColin Finck         return E_OUTOFMEMORY;
1174*c2c66affSColin Finck 
1175*c2c66affSColin Finck     callback->nsIAsyncVerifyRedirectCallback_iface.lpVtbl = &nsAsyncVerifyRedirectCallbackVtbl;
1176*c2c66affSColin Finck     callback->ref = 1;
1177*c2c66affSColin Finck 
1178*c2c66affSColin Finck     nsIHttpChannel_AddRef(&nschannel->nsIHttpChannel_iface);
1179*c2c66affSColin Finck     callback->nschannel = nschannel;
1180*c2c66affSColin Finck 
1181*c2c66affSColin Finck     IBindStatusCallback_AddRef(&bsc->bsc.IBindStatusCallback_iface);
1182*c2c66affSColin Finck     callback->bsc = bsc;
1183*c2c66affSColin Finck 
1184*c2c66affSColin Finck     *ret = callback;
1185*c2c66affSColin Finck     return S_OK;
1186*c2c66affSColin Finck }
1187*c2c66affSColin Finck 
nsChannelBSC_from_BSCallback(BSCallback * iface)1188*c2c66affSColin Finck static inline nsChannelBSC *nsChannelBSC_from_BSCallback(BSCallback *iface)
1189*c2c66affSColin Finck {
1190*c2c66affSColin Finck     return CONTAINING_RECORD(iface, nsChannelBSC, bsc);
1191*c2c66affSColin Finck }
1192*c2c66affSColin Finck 
nsChannelBSC_destroy(BSCallback * bsc)1193*c2c66affSColin Finck static void nsChannelBSC_destroy(BSCallback *bsc)
1194*c2c66affSColin Finck {
1195*c2c66affSColin Finck     nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1196*c2c66affSColin Finck 
1197*c2c66affSColin Finck     if(This->nschannel)
1198*c2c66affSColin Finck         nsIHttpChannel_Release(&This->nschannel->nsIHttpChannel_iface);
1199*c2c66affSColin Finck     if(This->nslistener)
1200*c2c66affSColin Finck         nsIStreamListener_Release(This->nslistener);
1201*c2c66affSColin Finck     if(This->nscontext)
1202*c2c66affSColin Finck         nsISupports_Release(This->nscontext);
1203*c2c66affSColin Finck     if(This->nsstream)
1204*c2c66affSColin Finck         nsIInputStream_Release(&This->nsstream->nsIInputStream_iface);
1205*c2c66affSColin Finck     heap_free(This);
1206*c2c66affSColin Finck }
1207*c2c66affSColin Finck 
nsChannelBSC_start_binding(BSCallback * bsc)1208*c2c66affSColin Finck static HRESULT nsChannelBSC_start_binding(BSCallback *bsc)
1209*c2c66affSColin Finck {
1210*c2c66affSColin Finck     nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1211*c2c66affSColin Finck 
1212*c2c66affSColin Finck     if(This->is_doc_channel)
1213*c2c66affSColin Finck         This->bsc.window->base.outer_window->base.inner_window->doc->skip_mutation_notif = FALSE;
1214*c2c66affSColin Finck 
1215*c2c66affSColin Finck     return S_OK;
1216*c2c66affSColin Finck }
1217*c2c66affSColin Finck 
nsChannelBSC_init_bindinfo(BSCallback * bsc)1218*c2c66affSColin Finck static HRESULT nsChannelBSC_init_bindinfo(BSCallback *bsc)
1219*c2c66affSColin Finck {
1220*c2c66affSColin Finck     nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1221*c2c66affSColin Finck     nsChannel *nschannel = This->nschannel;
1222*c2c66affSColin Finck     HRESULT hres;
1223*c2c66affSColin Finck 
1224*c2c66affSColin Finck     if(nschannel && nschannel->post_data_stream) {
1225*c2c66affSColin Finck         hres = read_post_data_stream(nschannel->post_data_stream, nschannel->post_data_contains_headers,
1226*c2c66affSColin Finck                 &nschannel->request_headers, &This->bsc.request_data);
1227*c2c66affSColin Finck         if(FAILED(hres))
1228*c2c66affSColin Finck             return hres;
1229*c2c66affSColin Finck     }
1230*c2c66affSColin Finck 
1231*c2c66affSColin Finck     return S_OK;
1232*c2c66affSColin Finck }
1233*c2c66affSColin Finck 
1234*c2c66affSColin Finck typedef struct {
1235*c2c66affSColin Finck     task_t header;
1236*c2c66affSColin Finck     nsChannelBSC *bsc;
1237*c2c66affSColin Finck } stop_request_task_t;
1238*c2c66affSColin Finck 
stop_request_proc(task_t * _task)1239*c2c66affSColin Finck static void stop_request_proc(task_t *_task)
1240*c2c66affSColin Finck {
1241*c2c66affSColin Finck     stop_request_task_t *task = (stop_request_task_t*)_task;
1242*c2c66affSColin Finck 
1243*c2c66affSColin Finck     TRACE("(%p)\n", task->bsc);
1244*c2c66affSColin Finck 
1245*c2c66affSColin Finck     list_remove(&task->bsc->bsc.entry);
1246*c2c66affSColin Finck     list_init(&task->bsc->bsc.entry);
1247*c2c66affSColin Finck     on_stop_nsrequest(task->bsc, S_OK);
1248*c2c66affSColin Finck }
1249*c2c66affSColin Finck 
stop_request_task_destr(task_t * _task)1250*c2c66affSColin Finck static void stop_request_task_destr(task_t *_task)
1251*c2c66affSColin Finck {
1252*c2c66affSColin Finck     stop_request_task_t *task = (stop_request_task_t*)_task;
1253*c2c66affSColin Finck 
1254*c2c66affSColin Finck     IBindStatusCallback_Release(&task->bsc->bsc.IBindStatusCallback_iface);
1255*c2c66affSColin Finck     heap_free(task);
1256*c2c66affSColin Finck }
1257*c2c66affSColin Finck 
async_stop_request(nsChannelBSC * This)1258*c2c66affSColin Finck static HRESULT async_stop_request(nsChannelBSC *This)
1259*c2c66affSColin Finck {
1260*c2c66affSColin Finck     stop_request_task_t *task;
1261*c2c66affSColin Finck 
1262*c2c66affSColin Finck     if(!This->bsc.readed) {
1263*c2c66affSColin Finck         TRACE("No data read, calling OnStartRequest\n");
1264*c2c66affSColin Finck         on_start_nsrequest(This);
1265*c2c66affSColin Finck     }
1266*c2c66affSColin Finck 
1267*c2c66affSColin Finck     task = heap_alloc(sizeof(*task));
1268*c2c66affSColin Finck     if(!task)
1269*c2c66affSColin Finck         return E_OUTOFMEMORY;
1270*c2c66affSColin Finck 
1271*c2c66affSColin Finck     IBindStatusCallback_AddRef(&This->bsc.IBindStatusCallback_iface);
1272*c2c66affSColin Finck     task->bsc = This;
1273*c2c66affSColin Finck 
1274*c2c66affSColin Finck     return push_task(&task->header, stop_request_proc, stop_request_task_destr, This->bsc.window->task_magic);
1275*c2c66affSColin Finck }
1276*c2c66affSColin Finck 
handle_navigation_error(nsChannelBSC * This,DWORD result)1277*c2c66affSColin Finck static void handle_navigation_error(nsChannelBSC *This, DWORD result)
1278*c2c66affSColin Finck {
1279*c2c66affSColin Finck     HTMLOuterWindow *outer_window;
1280*c2c66affSColin Finck     HTMLDocumentObj *doc;
1281*c2c66affSColin Finck     BOOL is_error_url;
1282*c2c66affSColin Finck     SAFEARRAY *sa;
1283*c2c66affSColin Finck     SAFEARRAYBOUND bound;
1284*c2c66affSColin Finck     VARIANT var, varOut;
1285*c2c66affSColin Finck     LONG ind;
1286*c2c66affSColin Finck     BSTR unk;
1287*c2c66affSColin Finck     HRESULT hres;
1288*c2c66affSColin Finck 
1289*c2c66affSColin Finck     if(!This->is_doc_channel || !This->bsc.window)
1290*c2c66affSColin Finck         return;
1291*c2c66affSColin Finck 
1292*c2c66affSColin Finck     outer_window = This->bsc.window->base.outer_window;
1293*c2c66affSColin Finck 
1294*c2c66affSColin Finck     doc = outer_window->doc_obj;
1295*c2c66affSColin Finck     if(!doc || !doc->doc_object_service || !doc->client)
1296*c2c66affSColin Finck         return;
1297*c2c66affSColin Finck 
1298*c2c66affSColin Finck     hres = IDocObjectService_IsErrorUrl(doc->doc_object_service,
1299*c2c66affSColin Finck             outer_window->url, &is_error_url);
1300*c2c66affSColin Finck     if(FAILED(hres) || is_error_url)
1301*c2c66affSColin Finck         return;
1302*c2c66affSColin Finck 
1303*c2c66affSColin Finck     if(!doc->client_cmdtrg)
1304*c2c66affSColin Finck         return;
1305*c2c66affSColin Finck 
1306*c2c66affSColin Finck     bound.lLbound = 0;
1307*c2c66affSColin Finck     bound.cElements = 8;
1308*c2c66affSColin Finck     sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
1309*c2c66affSColin Finck     if(!sa)
1310*c2c66affSColin Finck         return;
1311*c2c66affSColin Finck 
1312*c2c66affSColin Finck     ind = 0;
1313*c2c66affSColin Finck     V_VT(&var) = VT_I4;
1314*c2c66affSColin Finck     V_I4(&var) = result;
1315*c2c66affSColin Finck     SafeArrayPutElement(sa, &ind, &var);
1316*c2c66affSColin Finck 
1317*c2c66affSColin Finck     ind = 1;
1318*c2c66affSColin Finck     V_VT(&var) = VT_BSTR;
1319*c2c66affSColin Finck     V_BSTR(&var) = outer_window->url;
1320*c2c66affSColin Finck     SafeArrayPutElement(sa, &ind, &var);
1321*c2c66affSColin Finck 
1322*c2c66affSColin Finck     ind = 3;
1323*c2c66affSColin Finck     V_VT(&var) = VT_UNKNOWN;
1324*c2c66affSColin Finck     V_UNKNOWN(&var) = (IUnknown*)&outer_window->base.IHTMLWindow2_iface;
1325*c2c66affSColin Finck     SafeArrayPutElement(sa, &ind, &var);
1326*c2c66affSColin Finck 
1327*c2c66affSColin Finck     /* FIXME: what are the following fields for? */
1328*c2c66affSColin Finck     ind = 2;
1329*c2c66affSColin Finck     V_VT(&var) = VT_UNKNOWN;
1330*c2c66affSColin Finck     V_UNKNOWN(&var) = NULL;
1331*c2c66affSColin Finck     SafeArrayPutElement(sa, &ind, &var);
1332*c2c66affSColin Finck 
1333*c2c66affSColin Finck     ind = 4;
1334*c2c66affSColin Finck     V_VT(&var) = VT_BOOL;
1335*c2c66affSColin Finck     V_BOOL(&var) = FALSE;
1336*c2c66affSColin Finck     SafeArrayPutElement(sa, &ind, &var);
1337*c2c66affSColin Finck 
1338*c2c66affSColin Finck     ind = 5;
1339*c2c66affSColin Finck     V_VT(&var) = VT_BOOL;
1340*c2c66affSColin Finck     V_BOOL(&var) = FALSE;
1341*c2c66affSColin Finck     SafeArrayPutElement(sa, &ind, &var);
1342*c2c66affSColin Finck 
1343*c2c66affSColin Finck     ind = 6;
1344*c2c66affSColin Finck     V_VT(&var) = VT_BSTR;
1345*c2c66affSColin Finck     unk = SysAllocString(NULL);
1346*c2c66affSColin Finck     V_BSTR(&var) = unk;
1347*c2c66affSColin Finck     SafeArrayPutElement(sa, &ind, &var);
1348*c2c66affSColin Finck 
1349*c2c66affSColin Finck     ind = 7;
1350*c2c66affSColin Finck     V_VT(&var) = VT_UNKNOWN;
1351*c2c66affSColin Finck     V_UNKNOWN(&var) = NULL;
1352*c2c66affSColin Finck     SafeArrayPutElement(sa, &ind, &var);
1353*c2c66affSColin Finck 
1354*c2c66affSColin Finck     V_VT(&var) = VT_ARRAY;
1355*c2c66affSColin Finck     V_ARRAY(&var) = sa;
1356*c2c66affSColin Finck     V_VT(&varOut) = VT_BOOL;
1357*c2c66affSColin Finck     V_BOOL(&varOut) = VARIANT_TRUE;
1358*c2c66affSColin Finck     IOleCommandTarget_Exec(doc->client_cmdtrg, &CGID_DocHostCmdPriv, 1, 0, &var, FAILED(hres)?NULL:&varOut);
1359*c2c66affSColin Finck 
1360*c2c66affSColin Finck     SysFreeString(unk);
1361*c2c66affSColin Finck     SafeArrayDestroy(sa);
1362*c2c66affSColin Finck }
1363*c2c66affSColin Finck 
nsChannelBSC_stop_binding(BSCallback * bsc,HRESULT result)1364*c2c66affSColin Finck static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result)
1365*c2c66affSColin Finck {
1366*c2c66affSColin Finck     nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1367*c2c66affSColin Finck 
1368*c2c66affSColin Finck     if(result != E_ABORT) {
1369*c2c66affSColin Finck         if(FAILED(result))
1370*c2c66affSColin Finck             handle_navigation_error(This, result);
1371*c2c66affSColin Finck         else if(This->is_doc_channel && This->nschannel) {
1372*c2c66affSColin Finck             result = async_stop_request(This);
1373*c2c66affSColin Finck             if(SUCCEEDED(result))
1374*c2c66affSColin Finck                 return S_OK;
1375*c2c66affSColin Finck         }
1376*c2c66affSColin Finck     }
1377*c2c66affSColin Finck 
1378*c2c66affSColin Finck     on_stop_nsrequest(This, result);
1379*c2c66affSColin Finck     return S_OK;
1380*c2c66affSColin Finck }
1381*c2c66affSColin Finck 
nsChannelBSC_read_data(BSCallback * bsc,IStream * stream)1382*c2c66affSColin Finck static HRESULT nsChannelBSC_read_data(BSCallback *bsc, IStream *stream)
1383*c2c66affSColin Finck {
1384*c2c66affSColin Finck     nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1385*c2c66affSColin Finck 
1386*c2c66affSColin Finck     return read_stream_data(This, stream);
1387*c2c66affSColin Finck }
1388*c2c66affSColin Finck 
handle_redirect(nsChannelBSC * This,const WCHAR * new_url)1389*c2c66affSColin Finck static HRESULT handle_redirect(nsChannelBSC *This, const WCHAR *new_url)
1390*c2c66affSColin Finck {
1391*c2c66affSColin Finck     nsRedirectCallback *callback;
1392*c2c66affSColin Finck     nsIChannelEventSink *sink;
1393*c2c66affSColin Finck     nsChannel *new_channel;
1394*c2c66affSColin Finck     nsresult nsres;
1395*c2c66affSColin Finck     HRESULT hres;
1396*c2c66affSColin Finck 
1397*c2c66affSColin Finck     TRACE("(%p)->(%s)\n", This, debugstr_w(new_url));
1398*c2c66affSColin Finck 
1399*c2c66affSColin Finck     if(!This->nschannel || !This->nschannel->notif_callback)
1400*c2c66affSColin Finck         return S_OK;
1401*c2c66affSColin Finck 
1402*c2c66affSColin Finck     nsres = nsIInterfaceRequestor_GetInterface(This->nschannel->notif_callback, &IID_nsIChannelEventSink, (void**)&sink);
1403*c2c66affSColin Finck     if(NS_FAILED(nsres))
1404*c2c66affSColin Finck         return S_OK;
1405*c2c66affSColin Finck 
1406*c2c66affSColin Finck     hres = create_redirect_nschannel(new_url, This->nschannel, &new_channel);
1407*c2c66affSColin Finck     if(SUCCEEDED(hres)) {
1408*c2c66affSColin Finck         TRACE("%p %p->%p\n", This, This->nschannel, new_channel);
1409*c2c66affSColin Finck 
1410*c2c66affSColin Finck         hres = create_redirect_callback(new_channel, This, &callback);
1411*c2c66affSColin Finck         nsIHttpChannel_Release(&new_channel->nsIHttpChannel_iface);
1412*c2c66affSColin Finck     }
1413*c2c66affSColin Finck 
1414*c2c66affSColin Finck     if(SUCCEEDED(hres)) {
1415*c2c66affSColin Finck         nsres = nsIChannelEventSink_AsyncOnChannelRedirect(sink, (nsIChannel*)&This->nschannel->nsIHttpChannel_iface,
1416*c2c66affSColin Finck                 (nsIChannel*)&callback->nschannel->nsIHttpChannel_iface, REDIRECT_TEMPORARY, /* FIXME */
1417*c2c66affSColin Finck                 &callback->nsIAsyncVerifyRedirectCallback_iface);
1418*c2c66affSColin Finck 
1419*c2c66affSColin Finck         if(NS_FAILED(nsres))
1420*c2c66affSColin Finck             FIXME("AsyncOnChannelRedirect failed: %08x\n", hres);
1421*c2c66affSColin Finck         else if(This->nschannel != callback->nschannel)
1422*c2c66affSColin Finck             FIXME("nschannel not updated\n");
1423*c2c66affSColin Finck 
1424*c2c66affSColin Finck         nsIAsyncVerifyRedirectCallback_Release(&callback->nsIAsyncVerifyRedirectCallback_iface);
1425*c2c66affSColin Finck     }
1426*c2c66affSColin Finck 
1427*c2c66affSColin Finck     nsIChannelEventSink_Release(sink);
1428*c2c66affSColin Finck     return hres;
1429*c2c66affSColin Finck }
1430*c2c66affSColin Finck 
is_supported_doc_mime(const WCHAR * mime)1431*c2c66affSColin Finck static BOOL is_supported_doc_mime(const WCHAR *mime)
1432*c2c66affSColin Finck {
1433*c2c66affSColin Finck     char *nscat, *mimea;
1434*c2c66affSColin Finck     BOOL ret;
1435*c2c66affSColin Finck 
1436*c2c66affSColin Finck     mimea = heap_strdupWtoA(mime);
1437*c2c66affSColin Finck     if(!mimea)
1438*c2c66affSColin Finck         return FALSE;
1439*c2c66affSColin Finck 
1440*c2c66affSColin Finck     nscat = get_nscategory_entry("Gecko-Content-Viewers", mimea);
1441*c2c66affSColin Finck 
1442*c2c66affSColin Finck     ret = nscat != NULL && !strcmp(nscat, "@mozilla.org/content/document-loader-factory;1");
1443*c2c66affSColin Finck 
1444*c2c66affSColin Finck     heap_free(mimea);
1445*c2c66affSColin Finck     nsfree(nscat);
1446*c2c66affSColin Finck     return ret;
1447*c2c66affSColin Finck }
1448*c2c66affSColin Finck 
get_moniker_uri(IMoniker * mon)1449*c2c66affSColin Finck static IUri *get_moniker_uri(IMoniker *mon)
1450*c2c66affSColin Finck {
1451*c2c66affSColin Finck     IUriContainer *uri_container;
1452*c2c66affSColin Finck     IUri *ret = NULL;
1453*c2c66affSColin Finck     HRESULT hres;
1454*c2c66affSColin Finck 
1455*c2c66affSColin Finck     hres = IMoniker_QueryInterface(mon, &IID_IUriContainer, (void**)&uri_container);
1456*c2c66affSColin Finck     if(SUCCEEDED(hres)) {
1457*c2c66affSColin Finck         hres = IUriContainer_GetIUri(uri_container, &ret);
1458*c2c66affSColin Finck         IUriContainer_Release(uri_container);
1459*c2c66affSColin Finck         if(FAILED(hres))
1460*c2c66affSColin Finck             return NULL;
1461*c2c66affSColin Finck     }else {
1462*c2c66affSColin Finck         FIXME("No IUriContainer\n");
1463*c2c66affSColin Finck     }
1464*c2c66affSColin Finck 
1465*c2c66affSColin Finck     return ret;
1466*c2c66affSColin Finck }
1467*c2c66affSColin Finck 
handle_extern_mime_navigation(nsChannelBSC * This)1468*c2c66affSColin Finck static void handle_extern_mime_navigation(nsChannelBSC *This)
1469*c2c66affSColin Finck {
1470*c2c66affSColin Finck     IWebBrowserPriv2IE9 *webbrowser_priv;
1471*c2c66affSColin Finck     IOleCommandTarget *cmdtrg;
1472*c2c66affSColin Finck     HTMLDocumentObj *doc_obj;
1473*c2c66affSColin Finck     IBindCtx *bind_ctx;
1474*c2c66affSColin Finck     IUri *uri;
1475*c2c66affSColin Finck     VARIANT flags;
1476*c2c66affSColin Finck     HRESULT hres;
1477*c2c66affSColin Finck 
1478*c2c66affSColin Finck     if(!This->bsc.window || !This->bsc.window->base.outer_window || !This->bsc.window->base.outer_window->doc_obj)
1479*c2c66affSColin Finck         return;
1480*c2c66affSColin Finck 
1481*c2c66affSColin Finck     doc_obj = This->bsc.window->base.outer_window->doc_obj;
1482*c2c66affSColin Finck 
1483*c2c66affSColin Finck     hres = IOleClientSite_QueryInterface(doc_obj->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
1484*c2c66affSColin Finck     if(SUCCEEDED(hres)) {
1485*c2c66affSColin Finck         IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 62, 0, NULL, NULL);
1486*c2c66affSColin Finck         IOleCommandTarget_Release(cmdtrg);
1487*c2c66affSColin Finck     }
1488*c2c66affSColin Finck 
1489*c2c66affSColin Finck     set_document_navigation(doc_obj, FALSE);
1490*c2c66affSColin Finck 
1491*c2c66affSColin Finck     if(!doc_obj->webbrowser) {
1492*c2c66affSColin Finck         FIXME("unimplemented in non-webbrowser mode\n");
1493*c2c66affSColin Finck         return;
1494*c2c66affSColin Finck     }
1495*c2c66affSColin Finck 
1496*c2c66affSColin Finck     uri = get_moniker_uri(This->bsc.mon);
1497*c2c66affSColin Finck     if(!uri)
1498*c2c66affSColin Finck         return;
1499*c2c66affSColin Finck 
1500*c2c66affSColin Finck     hres = CreateBindCtx(0, &bind_ctx);
1501*c2c66affSColin Finck     if(FAILED(hres)) {
1502*c2c66affSColin Finck         IUri_Release(uri);
1503*c2c66affSColin Finck         return;
1504*c2c66affSColin Finck     }
1505*c2c66affSColin Finck 
1506*c2c66affSColin Finck     V_VT(&flags) = VT_I4;
1507*c2c66affSColin Finck     V_I4(&flags) = navHyperlink;
1508*c2c66affSColin Finck 
1509*c2c66affSColin Finck     hres = IUnknown_QueryInterface(doc_obj->webbrowser, &IID_IWebBrowserPriv2IE8, (void**)&webbrowser_priv);
1510*c2c66affSColin Finck     if(SUCCEEDED(hres)) {
1511*c2c66affSColin Finck         hres = IWebBrowserPriv2IE9_NavigateWithBindCtx2(webbrowser_priv, uri, &flags, NULL, NULL, NULL, bind_ctx, NULL, 0);
1512*c2c66affSColin Finck         IWebBrowserPriv2IE9_Release(webbrowser_priv);
1513*c2c66affSColin Finck     }else {
1514*c2c66affSColin Finck         IWebBrowserPriv *webbrowser_priv_old;
1515*c2c66affSColin Finck         VARIANT uriv;
1516*c2c66affSColin Finck 
1517*c2c66affSColin Finck         hres = IUnknown_QueryInterface(doc_obj->webbrowser, &IID_IWebBrowserPriv, (void**)&webbrowser_priv_old);
1518*c2c66affSColin Finck         if(SUCCEEDED(hres)) {
1519*c2c66affSColin Finck             V_VT(&uriv) = VT_BSTR;
1520*c2c66affSColin Finck             IUri_GetDisplayUri(uri, &V_BSTR(&uriv));
1521*c2c66affSColin Finck 
1522*c2c66affSColin Finck             hres = IWebBrowserPriv_NavigateWithBindCtx(webbrowser_priv_old, &uriv, &flags, NULL, NULL, NULL, bind_ctx, NULL);
1523*c2c66affSColin Finck 
1524*c2c66affSColin Finck             SysFreeString(V_BSTR(&uriv));
1525*c2c66affSColin Finck             IWebBrowserPriv_Release(webbrowser_priv_old);
1526*c2c66affSColin Finck         }
1527*c2c66affSColin Finck     }
1528*c2c66affSColin Finck 
1529*c2c66affSColin Finck     IUri_Release(uri);
1530*c2c66affSColin Finck }
1531*c2c66affSColin Finck 
nsChannelBSC_on_progress(BSCallback * bsc,ULONG status_code,LPCWSTR status_text)1532*c2c66affSColin Finck static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR status_text)
1533*c2c66affSColin Finck {
1534*c2c66affSColin Finck     nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1535*c2c66affSColin Finck 
1536*c2c66affSColin Finck     switch(status_code) {
1537*c2c66affSColin Finck     case BINDSTATUS_MIMETYPEAVAILABLE:
1538*c2c66affSColin Finck         if(This->is_doc_channel && !is_supported_doc_mime(status_text)) {
1539*c2c66affSColin Finck             FIXME("External MIME: %s\n", debugstr_w(status_text));
1540*c2c66affSColin Finck 
1541*c2c66affSColin Finck             handle_extern_mime_navigation(This);
1542*c2c66affSColin Finck 
1543*c2c66affSColin Finck             This->nschannel = NULL;
1544*c2c66affSColin Finck         }
1545*c2c66affSColin Finck 
1546*c2c66affSColin Finck         if(!This->nschannel)
1547*c2c66affSColin Finck             return S_OK;
1548*c2c66affSColin Finck 
1549*c2c66affSColin Finck         heap_free(This->nschannel->content_type);
1550*c2c66affSColin Finck         This->nschannel->content_type = heap_strdupWtoA(status_text);
1551*c2c66affSColin Finck         break;
1552*c2c66affSColin Finck     case BINDSTATUS_REDIRECTING:
1553*c2c66affSColin Finck         return handle_redirect(This, status_text);
1554*c2c66affSColin Finck     case BINDSTATUS_BEGINDOWNLOADDATA: {
1555*c2c66affSColin Finck         IWinInetHttpInfo *http_info;
1556*c2c66affSColin Finck         DWORD status, size = sizeof(DWORD);
1557*c2c66affSColin Finck         HRESULT hres;
1558*c2c66affSColin Finck 
1559*c2c66affSColin Finck         if(!This->bsc.binding)
1560*c2c66affSColin Finck             break;
1561*c2c66affSColin Finck 
1562*c2c66affSColin Finck         hres = IBinding_QueryInterface(This->bsc.binding, &IID_IWinInetHttpInfo, (void**)&http_info);
1563*c2c66affSColin Finck         if(FAILED(hres))
1564*c2c66affSColin Finck             break;
1565*c2c66affSColin Finck 
1566*c2c66affSColin Finck         hres = IWinInetHttpInfo_QueryInfo(http_info,
1567*c2c66affSColin Finck                 HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL, NULL);
1568*c2c66affSColin Finck         IWinInetHttpInfo_Release(http_info);
1569*c2c66affSColin Finck         if(FAILED(hres) || status == HTTP_STATUS_OK)
1570*c2c66affSColin Finck             break;
1571*c2c66affSColin Finck 
1572*c2c66affSColin Finck         handle_navigation_error(This, status);
1573*c2c66affSColin Finck     }
1574*c2c66affSColin Finck     }
1575*c2c66affSColin Finck 
1576*c2c66affSColin Finck     return S_OK;
1577*c2c66affSColin Finck }
1578*c2c66affSColin Finck 
process_response_status_text(const WCHAR * header,const WCHAR * header_end,char ** status_text)1579*c2c66affSColin Finck static HRESULT process_response_status_text(const WCHAR *header, const WCHAR *header_end, char **status_text)
1580*c2c66affSColin Finck {
1581*c2c66affSColin Finck     header = strchrW(header + 1, ' ');
1582*c2c66affSColin Finck     if(!header || header >= header_end)
1583*c2c66affSColin Finck         return E_FAIL;
1584*c2c66affSColin Finck     header = strchrW(header + 1, ' ');
1585*c2c66affSColin Finck     if(!header || header >= header_end)
1586*c2c66affSColin Finck         return E_FAIL;
1587*c2c66affSColin Finck     ++header;
1588*c2c66affSColin Finck 
1589*c2c66affSColin Finck     *status_text = heap_strndupWtoU(header, header_end - header);
1590*c2c66affSColin Finck 
1591*c2c66affSColin Finck     if(!*status_text)
1592*c2c66affSColin Finck         return E_OUTOFMEMORY;
1593*c2c66affSColin Finck 
1594*c2c66affSColin Finck     return S_OK;
1595*c2c66affSColin Finck }
1596*c2c66affSColin Finck 
nsChannelBSC_on_response(BSCallback * bsc,DWORD response_code,LPCWSTR response_headers)1597*c2c66affSColin Finck static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code,
1598*c2c66affSColin Finck         LPCWSTR response_headers)
1599*c2c66affSColin Finck {
1600*c2c66affSColin Finck     nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1601*c2c66affSColin Finck     char *str;
1602*c2c66affSColin Finck     HRESULT hres;
1603*c2c66affSColin Finck 
1604*c2c66affSColin Finck     This->response_processed = TRUE;
1605*c2c66affSColin Finck     This->nschannel->response_status = response_code;
1606*c2c66affSColin Finck 
1607*c2c66affSColin Finck     if(response_headers) {
1608*c2c66affSColin Finck         const WCHAR *headers;
1609*c2c66affSColin Finck 
1610*c2c66affSColin Finck         headers = strchrW(response_headers, '\r');
1611*c2c66affSColin Finck         hres = process_response_status_text(response_headers, headers, &str);
1612*c2c66affSColin Finck         if(FAILED(hres)) {
1613*c2c66affSColin Finck             WARN("parsing headers failed: %08x\n", hres);
1614*c2c66affSColin Finck             return hres;
1615*c2c66affSColin Finck         }
1616*c2c66affSColin Finck 
1617*c2c66affSColin Finck         heap_free(This->nschannel->response_status_text);
1618*c2c66affSColin Finck         This->nschannel->response_status_text = str;
1619*c2c66affSColin Finck 
1620*c2c66affSColin Finck         if(headers && headers[1] == '\n') {
1621*c2c66affSColin Finck             headers += 2;
1622*c2c66affSColin Finck             hres = process_response_headers(This, headers);
1623*c2c66affSColin Finck             if(FAILED(hres)) {
1624*c2c66affSColin Finck                 WARN("parsing headers failed: %08x\n", hres);
1625*c2c66affSColin Finck                 return hres;
1626*c2c66affSColin Finck             }
1627*c2c66affSColin Finck         }
1628*c2c66affSColin Finck     }
1629*c2c66affSColin Finck 
1630*c2c66affSColin Finck     return S_OK;
1631*c2c66affSColin Finck }
1632*c2c66affSColin Finck 
nsChannelBSC_beginning_transaction(BSCallback * bsc,WCHAR ** additional_headers)1633*c2c66affSColin Finck static HRESULT nsChannelBSC_beginning_transaction(BSCallback *bsc, WCHAR **additional_headers)
1634*c2c66affSColin Finck {
1635*c2c66affSColin Finck     nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1636*c2c66affSColin Finck     http_header_t *iter;
1637*c2c66affSColin Finck     DWORD len = 0;
1638*c2c66affSColin Finck     WCHAR *ptr;
1639*c2c66affSColin Finck 
1640*c2c66affSColin Finck     static const WCHAR content_lengthW[] =
1641*c2c66affSColin Finck         {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',0};
1642*c2c66affSColin Finck 
1643*c2c66affSColin Finck     if(!This->nschannel)
1644*c2c66affSColin Finck         return S_FALSE;
1645*c2c66affSColin Finck 
1646*c2c66affSColin Finck     LIST_FOR_EACH_ENTRY(iter, &This->nschannel->request_headers, http_header_t, entry) {
1647*c2c66affSColin Finck         if(strcmpW(iter->header, content_lengthW))
1648*c2c66affSColin Finck             len += strlenW(iter->header) + 2 /* ": " */ + strlenW(iter->data) + 2 /* "\r\n" */;
1649*c2c66affSColin Finck     }
1650*c2c66affSColin Finck 
1651*c2c66affSColin Finck     if(!len)
1652*c2c66affSColin Finck         return S_OK;
1653*c2c66affSColin Finck 
1654*c2c66affSColin Finck     *additional_headers = ptr = CoTaskMemAlloc((len+1)*sizeof(WCHAR));
1655*c2c66affSColin Finck     if(!ptr)
1656*c2c66affSColin Finck         return E_OUTOFMEMORY;
1657*c2c66affSColin Finck 
1658*c2c66affSColin Finck     LIST_FOR_EACH_ENTRY(iter, &This->nschannel->request_headers, http_header_t, entry) {
1659*c2c66affSColin Finck         if(!strcmpW(iter->header, content_lengthW))
1660*c2c66affSColin Finck             continue;
1661*c2c66affSColin Finck 
1662*c2c66affSColin Finck         len = strlenW(iter->header);
1663*c2c66affSColin Finck         memcpy(ptr, iter->header, len*sizeof(WCHAR));
1664*c2c66affSColin Finck         ptr += len;
1665*c2c66affSColin Finck 
1666*c2c66affSColin Finck         *ptr++ = ':';
1667*c2c66affSColin Finck         *ptr++ = ' ';
1668*c2c66affSColin Finck 
1669*c2c66affSColin Finck         len = strlenW(iter->data);
1670*c2c66affSColin Finck         memcpy(ptr, iter->data, len*sizeof(WCHAR));
1671*c2c66affSColin Finck         ptr += len;
1672*c2c66affSColin Finck 
1673*c2c66affSColin Finck         *ptr++ = '\r';
1674*c2c66affSColin Finck         *ptr++ = '\n';
1675*c2c66affSColin Finck     }
1676*c2c66affSColin Finck 
1677*c2c66affSColin Finck     *ptr = 0;
1678*c2c66affSColin Finck 
1679*c2c66affSColin Finck     return S_OK;
1680*c2c66affSColin Finck }
1681*c2c66affSColin Finck 
1682*c2c66affSColin Finck static const BSCallbackVtbl nsChannelBSCVtbl = {
1683*c2c66affSColin Finck     nsChannelBSC_destroy,
1684*c2c66affSColin Finck     nsChannelBSC_init_bindinfo,
1685*c2c66affSColin Finck     nsChannelBSC_start_binding,
1686*c2c66affSColin Finck     nsChannelBSC_stop_binding,
1687*c2c66affSColin Finck     nsChannelBSC_read_data,
1688*c2c66affSColin Finck     nsChannelBSC_on_progress,
1689*c2c66affSColin Finck     nsChannelBSC_on_response,
1690*c2c66affSColin Finck     nsChannelBSC_beginning_transaction
1691*c2c66affSColin Finck };
1692*c2c66affSColin Finck 
create_channelbsc(IMoniker * mon,const WCHAR * headers,BYTE * post_data,DWORD post_data_size,BOOL is_doc_binding,nsChannelBSC ** retval)1693*c2c66affSColin Finck HRESULT create_channelbsc(IMoniker *mon, const WCHAR *headers, BYTE *post_data, DWORD post_data_size,
1694*c2c66affSColin Finck         BOOL is_doc_binding, nsChannelBSC **retval)
1695*c2c66affSColin Finck {
1696*c2c66affSColin Finck     nsChannelBSC *ret;
1697*c2c66affSColin Finck     DWORD bindf;
1698*c2c66affSColin Finck 
1699*c2c66affSColin Finck     ret = heap_alloc_zero(sizeof(*ret));
1700*c2c66affSColin Finck     if(!ret)
1701*c2c66affSColin Finck         return E_OUTOFMEMORY;
1702*c2c66affSColin Finck 
1703*c2c66affSColin Finck     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
1704*c2c66affSColin Finck     if(post_data_size)
1705*c2c66affSColin Finck         bindf |= BINDF_FORMS_SUBMIT | BINDF_PRAGMA_NO_CACHE | BINDF_HYPERLINK | BINDF_GETNEWESTVERSION;
1706*c2c66affSColin Finck 
1707*c2c66affSColin Finck     init_bscallback(&ret->bsc, &nsChannelBSCVtbl, mon, bindf);
1708*c2c66affSColin Finck     ret->is_doc_channel = is_doc_binding;
1709*c2c66affSColin Finck 
1710*c2c66affSColin Finck     if(headers) {
1711*c2c66affSColin Finck         ret->bsc.request_data.headers = heap_strdupW(headers);
1712*c2c66affSColin Finck         if(!ret->bsc.request_data.headers) {
1713*c2c66affSColin Finck             IBindStatusCallback_Release(&ret->bsc.IBindStatusCallback_iface);
1714*c2c66affSColin Finck             return E_OUTOFMEMORY;
1715*c2c66affSColin Finck         }
1716*c2c66affSColin Finck     }
1717*c2c66affSColin Finck 
1718*c2c66affSColin Finck     if(post_data) {
1719*c2c66affSColin Finck         ret->bsc.request_data.post_data = GlobalAlloc(0, post_data_size+1);
1720*c2c66affSColin Finck         if(!ret->bsc.request_data.post_data) {
1721*c2c66affSColin Finck             release_request_data(&ret->bsc.request_data);
1722*c2c66affSColin Finck             IBindStatusCallback_Release(&ret->bsc.IBindStatusCallback_iface);
1723*c2c66affSColin Finck             return E_OUTOFMEMORY;
1724*c2c66affSColin Finck         }
1725*c2c66affSColin Finck 
1726*c2c66affSColin Finck         memcpy(ret->bsc.request_data.post_data, post_data, post_data_size);
1727*c2c66affSColin Finck         ((BYTE*)ret->bsc.request_data.post_data)[post_data_size] = 0;
1728*c2c66affSColin Finck         ret->bsc.request_data.post_data_len = post_data_size;
1729*c2c66affSColin Finck     }
1730*c2c66affSColin Finck 
1731*c2c66affSColin Finck     TRACE("created %p\n", ret);
1732*c2c66affSColin Finck     *retval = ret;
1733*c2c66affSColin Finck     return S_OK;
1734*c2c66affSColin Finck }
1735*c2c66affSColin Finck 
1736*c2c66affSColin Finck typedef struct {
1737*c2c66affSColin Finck     task_t header;
1738*c2c66affSColin Finck     HTMLOuterWindow *window;
1739*c2c66affSColin Finck     HTMLInnerWindow *pending_window;
1740*c2c66affSColin Finck } start_doc_binding_task_t;
1741*c2c66affSColin Finck 
start_doc_binding_proc(task_t * _task)1742*c2c66affSColin Finck static void start_doc_binding_proc(task_t *_task)
1743*c2c66affSColin Finck {
1744*c2c66affSColin Finck     start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task;
1745*c2c66affSColin Finck 
1746*c2c66affSColin Finck     set_current_mon(task->window, task->pending_window->bscallback->bsc.mon, BINDING_NAVIGATED);
1747*c2c66affSColin Finck     start_binding(task->pending_window, &task->pending_window->bscallback->bsc, NULL);
1748*c2c66affSColin Finck }
1749*c2c66affSColin Finck 
start_doc_binding_task_destr(task_t * _task)1750*c2c66affSColin Finck static void start_doc_binding_task_destr(task_t *_task)
1751*c2c66affSColin Finck {
1752*c2c66affSColin Finck     start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task;
1753*c2c66affSColin Finck 
1754*c2c66affSColin Finck     IHTMLWindow2_Release(&task->pending_window->base.IHTMLWindow2_iface);
1755*c2c66affSColin Finck     heap_free(task);
1756*c2c66affSColin Finck }
1757*c2c66affSColin Finck 
async_start_doc_binding(HTMLOuterWindow * window,HTMLInnerWindow * pending_window)1758*c2c66affSColin Finck HRESULT async_start_doc_binding(HTMLOuterWindow *window, HTMLInnerWindow *pending_window)
1759*c2c66affSColin Finck {
1760*c2c66affSColin Finck     start_doc_binding_task_t *task;
1761*c2c66affSColin Finck 
1762*c2c66affSColin Finck     TRACE("%p\n", pending_window);
1763*c2c66affSColin Finck 
1764*c2c66affSColin Finck     task = heap_alloc(sizeof(start_doc_binding_task_t));
1765*c2c66affSColin Finck     if(!task)
1766*c2c66affSColin Finck         return E_OUTOFMEMORY;
1767*c2c66affSColin Finck 
1768*c2c66affSColin Finck     task->window = window;
1769*c2c66affSColin Finck     task->pending_window = pending_window;
1770*c2c66affSColin Finck     IHTMLWindow2_AddRef(&pending_window->base.IHTMLWindow2_iface);
1771*c2c66affSColin Finck 
1772*c2c66affSColin Finck     return push_task(&task->header, start_doc_binding_proc, start_doc_binding_task_destr, pending_window->task_magic);
1773*c2c66affSColin Finck }
1774*c2c66affSColin Finck 
abort_window_bindings(HTMLInnerWindow * window)1775*c2c66affSColin Finck void abort_window_bindings(HTMLInnerWindow *window)
1776*c2c66affSColin Finck {
1777*c2c66affSColin Finck     BSCallback *iter;
1778*c2c66affSColin Finck 
1779*c2c66affSColin Finck     remove_target_tasks(window->task_magic);
1780*c2c66affSColin Finck 
1781*c2c66affSColin Finck     while(!list_empty(&window->bindings)) {
1782*c2c66affSColin Finck         iter = LIST_ENTRY(window->bindings.next, BSCallback, entry);
1783*c2c66affSColin Finck 
1784*c2c66affSColin Finck         TRACE("Aborting %p\n", iter);
1785*c2c66affSColin Finck 
1786*c2c66affSColin Finck         IBindStatusCallback_AddRef(&iter->IBindStatusCallback_iface);
1787*c2c66affSColin Finck 
1788*c2c66affSColin Finck         if(iter->binding)
1789*c2c66affSColin Finck             IBinding_Abort(iter->binding);
1790*c2c66affSColin Finck         else
1791*c2c66affSColin Finck             iter->vtbl->stop_binding(iter, E_ABORT);
1792*c2c66affSColin Finck 
1793*c2c66affSColin Finck         iter->window = NULL;
1794*c2c66affSColin Finck         list_remove(&iter->entry);
1795*c2c66affSColin Finck         list_init(&iter->entry);
1796*c2c66affSColin Finck 
1797*c2c66affSColin Finck         IBindStatusCallback_Release(&iter->IBindStatusCallback_iface);
1798*c2c66affSColin Finck     }
1799*c2c66affSColin Finck 
1800*c2c66affSColin Finck     if(window->bscallback) {
1801*c2c66affSColin Finck         IBindStatusCallback_Release(&window->bscallback->bsc.IBindStatusCallback_iface);
1802*c2c66affSColin Finck         window->bscallback = NULL;
1803*c2c66affSColin Finck     }
1804*c2c66affSColin Finck 
1805*c2c66affSColin Finck     if(window->mon) {
1806*c2c66affSColin Finck         IMoniker_Release(window->mon);
1807*c2c66affSColin Finck         window->mon = NULL;
1808*c2c66affSColin Finck     }
1809*c2c66affSColin Finck }
1810*c2c66affSColin Finck 
channelbsc_load_stream(HTMLInnerWindow * pending_window,IMoniker * mon,IStream * stream)1811*c2c66affSColin Finck HRESULT channelbsc_load_stream(HTMLInnerWindow *pending_window, IMoniker *mon, IStream *stream)
1812*c2c66affSColin Finck {
1813*c2c66affSColin Finck     nsChannelBSC *bscallback = pending_window->bscallback;
1814*c2c66affSColin Finck     HRESULT hres = S_OK;
1815*c2c66affSColin Finck 
1816*c2c66affSColin Finck     if(!bscallback->nschannel) {
1817*c2c66affSColin Finck         ERR("NULL nschannel\n");
1818*c2c66affSColin Finck         return E_FAIL;
1819*c2c66affSColin Finck     }
1820*c2c66affSColin Finck 
1821*c2c66affSColin Finck     bscallback->nschannel->content_type = heap_strdupA("text/html");
1822*c2c66affSColin Finck     if(!bscallback->nschannel->content_type)
1823*c2c66affSColin Finck         return E_OUTOFMEMORY;
1824*c2c66affSColin Finck 
1825*c2c66affSColin Finck     set_current_mon(pending_window->base.outer_window, mon, 0);
1826*c2c66affSColin Finck 
1827*c2c66affSColin Finck     bscallback->bsc.window = pending_window;
1828*c2c66affSColin Finck     if(stream)
1829*c2c66affSColin Finck         hres = read_stream_data(bscallback, stream);
1830*c2c66affSColin Finck     if(SUCCEEDED(hres))
1831*c2c66affSColin Finck         hres = async_stop_request(bscallback);
1832*c2c66affSColin Finck     if(FAILED(hres))
1833*c2c66affSColin Finck         IBindStatusCallback_OnStopBinding(&bscallback->bsc.IBindStatusCallback_iface, hres,
1834*c2c66affSColin Finck                 ERROR_SUCCESS);
1835*c2c66affSColin Finck 
1836*c2c66affSColin Finck     return hres;
1837*c2c66affSColin Finck }
1838*c2c66affSColin Finck 
channelbsc_set_channel(nsChannelBSC * This,nsChannel * channel,nsIStreamListener * listener,nsISupports * context)1839*c2c66affSColin Finck void channelbsc_set_channel(nsChannelBSC *This, nsChannel *channel, nsIStreamListener *listener, nsISupports *context)
1840*c2c66affSColin Finck {
1841*c2c66affSColin Finck     nsIHttpChannel_AddRef(&channel->nsIHttpChannel_iface);
1842*c2c66affSColin Finck     This->nschannel = channel;
1843*c2c66affSColin Finck 
1844*c2c66affSColin Finck     nsIStreamListener_AddRef(listener);
1845*c2c66affSColin Finck     This->nslistener = listener;
1846*c2c66affSColin Finck 
1847*c2c66affSColin Finck     if(context) {
1848*c2c66affSColin Finck         nsISupports_AddRef(context);
1849*c2c66affSColin Finck         This->nscontext = context;
1850*c2c66affSColin Finck     }
1851*c2c66affSColin Finck 
1852*c2c66affSColin Finck     if(This->bsc.request_data.headers) {
1853*c2c66affSColin Finck         HRESULT hres;
1854*c2c66affSColin Finck 
1855*c2c66affSColin Finck         hres = parse_headers(This->bsc.request_data.headers, &channel->request_headers);
1856*c2c66affSColin Finck         heap_free(This->bsc.request_data.headers);
1857*c2c66affSColin Finck         This->bsc.request_data.headers = NULL;
1858*c2c66affSColin Finck         if(FAILED(hres))
1859*c2c66affSColin Finck             WARN("parse_headers failed: %08x\n", hres);
1860*c2c66affSColin Finck     }
1861*c2c66affSColin Finck }
1862*c2c66affSColin Finck 
1863*c2c66affSColin Finck typedef struct {
1864*c2c66affSColin Finck     task_t header;
1865*c2c66affSColin Finck     HTMLOuterWindow *window;
1866*c2c66affSColin Finck     IUri *uri;
1867*c2c66affSColin Finck } navigate_javascript_task_t;
1868*c2c66affSColin Finck 
navigate_javascript_proc(task_t * _task)1869*c2c66affSColin Finck static void navigate_javascript_proc(task_t *_task)
1870*c2c66affSColin Finck {
1871*c2c66affSColin Finck     navigate_javascript_task_t *task = (navigate_javascript_task_t*)_task;
1872*c2c66affSColin Finck     HTMLOuterWindow *window = task->window;
1873*c2c66affSColin Finck     VARIANT v;
1874*c2c66affSColin Finck     BSTR code;
1875*c2c66affSColin Finck     HRESULT hres;
1876*c2c66affSColin Finck 
1877*c2c66affSColin Finck     static const WCHAR jscriptW[] = {'j','s','c','r','i','p','t',0};
1878*c2c66affSColin Finck 
1879*c2c66affSColin Finck     task->window->readystate = READYSTATE_COMPLETE;
1880*c2c66affSColin Finck 
1881*c2c66affSColin Finck     hres = IUri_GetPath(task->uri, &code);
1882*c2c66affSColin Finck     if(FAILED(hres))
1883*c2c66affSColin Finck         return;
1884*c2c66affSColin Finck 
1885*c2c66affSColin Finck     hres = UrlUnescapeW(code, NULL, NULL, URL_UNESCAPE_INPLACE);
1886*c2c66affSColin Finck     if(FAILED(hres)) {
1887*c2c66affSColin Finck         SysFreeString(code);
1888*c2c66affSColin Finck         return;
1889*c2c66affSColin Finck     }
1890*c2c66affSColin Finck 
1891*c2c66affSColin Finck     set_download_state(window->doc_obj, 1);
1892*c2c66affSColin Finck 
1893*c2c66affSColin Finck     V_VT(&v) = VT_EMPTY;
1894*c2c66affSColin Finck     hres = exec_script(window->base.inner_window, code, jscriptW, &v);
1895*c2c66affSColin Finck     SysFreeString(code);
1896*c2c66affSColin Finck     if(SUCCEEDED(hres) && V_VT(&v) != VT_EMPTY) {
1897*c2c66affSColin Finck         FIXME("javascirpt URL returned %s\n", debugstr_variant(&v));
1898*c2c66affSColin Finck         VariantClear(&v);
1899*c2c66affSColin Finck     }
1900*c2c66affSColin Finck 
1901*c2c66affSColin Finck     if(window->doc_obj->view_sink)
1902*c2c66affSColin Finck         IAdviseSink_OnViewChange(window->doc_obj->view_sink, DVASPECT_CONTENT, -1);
1903*c2c66affSColin Finck 
1904*c2c66affSColin Finck     set_download_state(window->doc_obj, 0);
1905*c2c66affSColin Finck }
1906*c2c66affSColin Finck 
navigate_javascript_task_destr(task_t * _task)1907*c2c66affSColin Finck static void navigate_javascript_task_destr(task_t *_task)
1908*c2c66affSColin Finck {
1909*c2c66affSColin Finck     navigate_javascript_task_t *task = (navigate_javascript_task_t*)_task;
1910*c2c66affSColin Finck 
1911*c2c66affSColin Finck     IUri_Release(task->uri);
1912*c2c66affSColin Finck     heap_free(task);
1913*c2c66affSColin Finck }
1914*c2c66affSColin Finck 
1915*c2c66affSColin Finck typedef struct {
1916*c2c66affSColin Finck     task_t header;
1917*c2c66affSColin Finck     HTMLOuterWindow *window;
1918*c2c66affSColin Finck     nsChannelBSC *bscallback;
1919*c2c66affSColin Finck     DWORD flags;
1920*c2c66affSColin Finck     IMoniker *mon;
1921*c2c66affSColin Finck     IUri *uri;
1922*c2c66affSColin Finck } navigate_task_t;
1923*c2c66affSColin Finck 
navigate_proc(task_t * _task)1924*c2c66affSColin Finck static void navigate_proc(task_t *_task)
1925*c2c66affSColin Finck {
1926*c2c66affSColin Finck     navigate_task_t *task = (navigate_task_t*)_task;
1927*c2c66affSColin Finck     HRESULT hres;
1928*c2c66affSColin Finck 
1929*c2c66affSColin Finck     hres = set_moniker(task->window, task->mon, task->uri, NULL, task->bscallback, TRUE);
1930*c2c66affSColin Finck     if(SUCCEEDED(hres)) {
1931*c2c66affSColin Finck         set_current_mon(task->window, task->bscallback->bsc.mon, task->flags);
1932*c2c66affSColin Finck         set_current_uri(task->window, task->uri);
1933*c2c66affSColin Finck         start_binding(task->window->pending_window, &task->bscallback->bsc, NULL);
1934*c2c66affSColin Finck     }
1935*c2c66affSColin Finck }
1936*c2c66affSColin Finck 
navigate_task_destr(task_t * _task)1937*c2c66affSColin Finck static void navigate_task_destr(task_t *_task)
1938*c2c66affSColin Finck {
1939*c2c66affSColin Finck     navigate_task_t *task = (navigate_task_t*)_task;
1940*c2c66affSColin Finck 
1941*c2c66affSColin Finck     IBindStatusCallback_Release(&task->bscallback->bsc.IBindStatusCallback_iface);
1942*c2c66affSColin Finck     IMoniker_Release(task->mon);
1943*c2c66affSColin Finck     IUri_Release(task->uri);
1944*c2c66affSColin Finck     heap_free(task);
1945*c2c66affSColin Finck }
1946*c2c66affSColin Finck 
navigate_fragment(HTMLOuterWindow * window,IUri * uri)1947*c2c66affSColin Finck static HRESULT navigate_fragment(HTMLOuterWindow *window, IUri *uri)
1948*c2c66affSColin Finck {
1949*c2c66affSColin Finck     nsIDOMLocation *nslocation;
1950*c2c66affSColin Finck     nsAString nsfrag_str;
1951*c2c66affSColin Finck     WCHAR *selector;
1952*c2c66affSColin Finck     BSTR frag;
1953*c2c66affSColin Finck     nsresult nsres;
1954*c2c66affSColin Finck     HRESULT hres;
1955*c2c66affSColin Finck 
1956*c2c66affSColin Finck     const WCHAR selector_formatW[] = {'a','[','i','d','=','"','%','s','"',']',0};
1957*c2c66affSColin Finck 
1958*c2c66affSColin Finck     set_current_uri(window, uri);
1959*c2c66affSColin Finck 
1960*c2c66affSColin Finck     nsres = nsIDOMWindow_GetLocation(window->nswindow, &nslocation);
1961*c2c66affSColin Finck     if(FAILED(nsres) || !nslocation)
1962*c2c66affSColin Finck         return E_FAIL;
1963*c2c66affSColin Finck 
1964*c2c66affSColin Finck     hres = IUri_GetFragment(uri, &frag);
1965*c2c66affSColin Finck     if(FAILED(hres)) {
1966*c2c66affSColin Finck         nsIDOMLocation_Release(nslocation);
1967*c2c66affSColin Finck         return hres;
1968*c2c66affSColin Finck     }
1969*c2c66affSColin Finck 
1970*c2c66affSColin Finck     nsAString_InitDepend(&nsfrag_str, frag);
1971*c2c66affSColin Finck     nsres = nsIDOMLocation_SetHash(nslocation, &nsfrag_str);
1972*c2c66affSColin Finck     nsAString_Finish(&nsfrag_str);
1973*c2c66affSColin Finck     nsIDOMLocation_Release(nslocation);
1974*c2c66affSColin Finck     if(NS_FAILED(nsres))
1975*c2c66affSColin Finck         ERR("SetHash failed: %08x\n", nsres);
1976*c2c66affSColin Finck 
1977*c2c66affSColin Finck     /*
1978*c2c66affSColin Finck      * IE supports scrolling to anchor elements with "#hash" ids (note that '#' is part of the id),
1979*c2c66affSColin Finck      * while Gecko scrolls only to elements with "hash" ids. We scroll the page ourselves if
1980*c2c66affSColin Finck      * a[id="#hash"] element can be found.
1981*c2c66affSColin Finck      */
1982*c2c66affSColin Finck     selector = heap_alloc(sizeof(selector_formatW)+SysStringLen(frag)*sizeof(WCHAR));
1983*c2c66affSColin Finck     if(selector) {
1984*c2c66affSColin Finck         nsIDOMElement *nselem = NULL;
1985*c2c66affSColin Finck         nsAString selector_str;
1986*c2c66affSColin Finck 
1987*c2c66affSColin Finck         sprintfW(selector, selector_formatW, frag);
1988*c2c66affSColin Finck         nsAString_InitDepend(&selector_str, selector);
1989*c2c66affSColin Finck         /* NOTE: Gecko doesn't set result to NULL if there is no match, so nselem must be initialized */
1990*c2c66affSColin Finck         nsres = nsIDOMHTMLDocument_QuerySelector(window->base.inner_window->doc->nsdoc, &selector_str, &nselem);
1991*c2c66affSColin Finck         nsAString_Finish(&selector_str);
1992*c2c66affSColin Finck         heap_free(selector);
1993*c2c66affSColin Finck         if(NS_SUCCEEDED(nsres) && nselem) {
1994*c2c66affSColin Finck             nsIDOMHTMLElement *html_elem;
1995*c2c66affSColin Finck 
1996*c2c66affSColin Finck             nsres = nsIDOMElement_QueryInterface(nselem, &IID_nsIDOMHTMLElement, (void**)&html_elem);
1997*c2c66affSColin Finck             nsIDOMElement_Release(nselem);
1998*c2c66affSColin Finck             if(NS_SUCCEEDED(nsres)) {
1999*c2c66affSColin Finck                 nsIDOMHTMLElement_ScrollIntoView(html_elem, TRUE, 1);
2000*c2c66affSColin Finck                 nsIDOMHTMLElement_Release(html_elem);
2001*c2c66affSColin Finck             }
2002*c2c66affSColin Finck         }
2003*c2c66affSColin Finck     }
2004*c2c66affSColin Finck 
2005*c2c66affSColin Finck     SysFreeString(frag);
2006*c2c66affSColin Finck 
2007*c2c66affSColin Finck     if(window->doc_obj->doc_object_service) {
2008*c2c66affSColin Finck         IDocObjectService_FireNavigateComplete2(window->doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0x10);
2009*c2c66affSColin Finck         IDocObjectService_FireDocumentComplete(window->doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0);
2010*c2c66affSColin Finck 
2011*c2c66affSColin Finck     }
2012*c2c66affSColin Finck 
2013*c2c66affSColin Finck     return S_OK;
2014*c2c66affSColin Finck }
2015*c2c66affSColin Finck 
super_navigate(HTMLOuterWindow * window,IUri * uri,DWORD flags,const WCHAR * headers,BYTE * post_data,DWORD post_data_size)2016*c2c66affSColin Finck HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WCHAR *headers, BYTE *post_data, DWORD post_data_size)
2017*c2c66affSColin Finck {
2018*c2c66affSColin Finck     nsChannelBSC *bsc;
2019*c2c66affSColin Finck     IUri *uri_nofrag;
2020*c2c66affSColin Finck     IMoniker *mon;
2021*c2c66affSColin Finck     DWORD scheme;
2022*c2c66affSColin Finck     HRESULT hres;
2023*c2c66affSColin Finck 
2024*c2c66affSColin Finck     uri_nofrag = get_uri_nofrag(uri);
2025*c2c66affSColin Finck     if(!uri_nofrag)
2026*c2c66affSColin Finck         return E_FAIL;
2027*c2c66affSColin Finck 
2028*c2c66affSColin Finck     if(window->doc_obj->client && !(flags & BINDING_REFRESH)) {
2029*c2c66affSColin Finck         IOleCommandTarget *cmdtrg;
2030*c2c66affSColin Finck 
2031*c2c66affSColin Finck         hres = IOleClientSite_QueryInterface(window->doc_obj->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
2032*c2c66affSColin Finck         if(SUCCEEDED(hres)) {
2033*c2c66affSColin Finck             VARIANT in, out;
2034*c2c66affSColin Finck             BSTR url_str;
2035*c2c66affSColin Finck 
2036*c2c66affSColin Finck             hres = IUri_GetDisplayUri(uri_nofrag, &url_str);
2037*c2c66affSColin Finck             if(SUCCEEDED(hres)) {
2038*c2c66affSColin Finck                 V_VT(&in) = VT_BSTR;
2039*c2c66affSColin Finck                 V_BSTR(&in) = url_str;
2040*c2c66affSColin Finck                 V_VT(&out) = VT_BOOL;
2041*c2c66affSColin Finck                 V_BOOL(&out) = VARIANT_TRUE;
2042*c2c66affSColin Finck                 hres = IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 67, 0, &in, &out);
2043*c2c66affSColin Finck                 IOleCommandTarget_Release(cmdtrg);
2044*c2c66affSColin Finck                 if(SUCCEEDED(hres))
2045*c2c66affSColin Finck                     VariantClear(&out);
2046*c2c66affSColin Finck                 SysFreeString(url_str);
2047*c2c66affSColin Finck             }
2048*c2c66affSColin Finck         }
2049*c2c66affSColin Finck     }
2050*c2c66affSColin Finck 
2051*c2c66affSColin Finck     if(!(flags & BINDING_NOFRAG) && window->uri_nofrag && !post_data_size) {
2052*c2c66affSColin Finck         BOOL eq;
2053*c2c66affSColin Finck 
2054*c2c66affSColin Finck         hres = IUri_IsEqual(uri_nofrag, window->uri_nofrag, &eq);
2055*c2c66affSColin Finck         if(SUCCEEDED(hres) && eq) {
2056*c2c66affSColin Finck             IUri_Release(uri_nofrag);
2057*c2c66affSColin Finck             TRACE("fragment navigate\n");
2058*c2c66affSColin Finck             return navigate_fragment(window, uri);
2059*c2c66affSColin Finck         }
2060*c2c66affSColin Finck     }
2061*c2c66affSColin Finck 
2062*c2c66affSColin Finck     hres = CreateURLMonikerEx2(NULL, uri_nofrag, &mon, URL_MK_UNIFORM);
2063*c2c66affSColin Finck     IUri_Release(uri_nofrag);
2064*c2c66affSColin Finck     if(FAILED(hres))
2065*c2c66affSColin Finck         return hres;
2066*c2c66affSColin Finck 
2067*c2c66affSColin Finck     /* FIXME: Why not set_ready_state? */
2068*c2c66affSColin Finck     window->readystate = READYSTATE_UNINITIALIZED;
2069*c2c66affSColin Finck 
2070*c2c66affSColin Finck     hres = create_channelbsc(mon, headers, post_data, post_data_size, TRUE, &bsc);
2071*c2c66affSColin Finck     if(FAILED(hres)) {
2072*c2c66affSColin Finck         IMoniker_Release(mon);
2073*c2c66affSColin Finck         return hres;
2074*c2c66affSColin Finck     }
2075*c2c66affSColin Finck 
2076*c2c66affSColin Finck     prepare_for_binding(&window->doc_obj->basedoc, mon, flags);
2077*c2c66affSColin Finck 
2078*c2c66affSColin Finck     hres = IUri_GetScheme(uri, &scheme);
2079*c2c66affSColin Finck     if(SUCCEEDED(hres) && scheme == URL_SCHEME_JAVASCRIPT) {
2080*c2c66affSColin Finck         navigate_javascript_task_t *task;
2081*c2c66affSColin Finck 
2082*c2c66affSColin Finck         IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2083*c2c66affSColin Finck         IMoniker_Release(mon);
2084*c2c66affSColin Finck 
2085*c2c66affSColin Finck         task = heap_alloc(sizeof(*task));
2086*c2c66affSColin Finck         if(!task)
2087*c2c66affSColin Finck             return E_OUTOFMEMORY;
2088*c2c66affSColin Finck 
2089*c2c66affSColin Finck         /* Why silently? */
2090*c2c66affSColin Finck         window->readystate = READYSTATE_COMPLETE;
2091*c2c66affSColin Finck         if(!(flags & BINDING_FROMHIST))
2092*c2c66affSColin Finck             call_docview_84(window->doc_obj);
2093*c2c66affSColin Finck 
2094*c2c66affSColin Finck         IUri_AddRef(uri);
2095*c2c66affSColin Finck         task->window = window;
2096*c2c66affSColin Finck         task->uri = uri;
2097*c2c66affSColin Finck         hres = push_task(&task->header, navigate_javascript_proc, navigate_javascript_task_destr, window->task_magic);
2098*c2c66affSColin Finck     }else if(flags & BINDING_SUBMIT) {
2099*c2c66affSColin Finck         hres = set_moniker(window, mon, uri, NULL, bsc, TRUE);
2100*c2c66affSColin Finck         if(SUCCEEDED(hres))
2101*c2c66affSColin Finck             hres = start_binding(window->pending_window, &bsc->bsc, NULL);
2102*c2c66affSColin Finck         IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2103*c2c66affSColin Finck         IMoniker_Release(mon);
2104*c2c66affSColin Finck     }else {
2105*c2c66affSColin Finck         navigate_task_t *task;
2106*c2c66affSColin Finck 
2107*c2c66affSColin Finck         task = heap_alloc(sizeof(*task));
2108*c2c66affSColin Finck         if(!task) {
2109*c2c66affSColin Finck             IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2110*c2c66affSColin Finck             IMoniker_Release(mon);
2111*c2c66affSColin Finck             return E_OUTOFMEMORY;
2112*c2c66affSColin Finck         }
2113*c2c66affSColin Finck 
2114*c2c66affSColin Finck         /* Silently and repeated when real loading starts? */
2115*c2c66affSColin Finck         window->readystate = READYSTATE_LOADING;
2116*c2c66affSColin Finck         if(!(flags & (BINDING_FROMHIST|BINDING_REFRESH)))
2117*c2c66affSColin Finck             call_docview_84(window->doc_obj);
2118*c2c66affSColin Finck 
2119*c2c66affSColin Finck         task->window = window;
2120*c2c66affSColin Finck         task->bscallback = bsc;
2121*c2c66affSColin Finck         task->flags = flags;
2122*c2c66affSColin Finck         task->mon = mon;
2123*c2c66affSColin Finck 
2124*c2c66affSColin Finck         IUri_AddRef(uri);
2125*c2c66affSColin Finck         task->uri = uri;
2126*c2c66affSColin Finck         hres = push_task(&task->header, navigate_proc, navigate_task_destr, window->task_magic);
2127*c2c66affSColin Finck     }
2128*c2c66affSColin Finck 
2129*c2c66affSColin Finck     return hres;
2130*c2c66affSColin Finck }
2131*c2c66affSColin Finck 
navigate_new_window(HTMLOuterWindow * window,IUri * uri,const WCHAR * name,request_data_t * request_data,IHTMLWindow2 ** ret)2132*c2c66affSColin Finck HRESULT navigate_new_window(HTMLOuterWindow *window, IUri *uri, const WCHAR *name, request_data_t *request_data, IHTMLWindow2 **ret)
2133*c2c66affSColin Finck {
2134*c2c66affSColin Finck     IWebBrowser2 *web_browser;
2135*c2c66affSColin Finck     IHTMLWindow2 *new_window;
2136*c2c66affSColin Finck     IBindCtx *bind_ctx;
2137*c2c66affSColin Finck     nsChannelBSC *bsc;
2138*c2c66affSColin Finck     HRESULT hres;
2139*c2c66affSColin Finck 
2140*c2c66affSColin Finck     if(request_data)
2141*c2c66affSColin Finck         hres = create_channelbsc(NULL, request_data->headers,
2142*c2c66affSColin Finck                 request_data->post_data, request_data->post_data_len, FALSE,
2143*c2c66affSColin Finck                 &bsc);
2144*c2c66affSColin Finck     else
2145*c2c66affSColin Finck         hres = create_channelbsc(NULL, NULL, NULL, 0, FALSE, &bsc);
2146*c2c66affSColin Finck     if(FAILED(hres))
2147*c2c66affSColin Finck         return hres;
2148*c2c66affSColin Finck 
2149*c2c66affSColin Finck     hres = CreateAsyncBindCtx(0, &bsc->bsc.IBindStatusCallback_iface, NULL, &bind_ctx);
2150*c2c66affSColin Finck     if(FAILED(hres)) {
2151*c2c66affSColin Finck         IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2152*c2c66affSColin Finck         return hres;
2153*c2c66affSColin Finck     }
2154*c2c66affSColin Finck 
2155*c2c66affSColin Finck     hres = CoCreateInstance(&CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER,
2156*c2c66affSColin Finck             &IID_IWebBrowser2, (void**)&web_browser);
2157*c2c66affSColin Finck     if(SUCCEEDED(hres)) {
2158*c2c66affSColin Finck         ITargetFramePriv2 *target_frame_priv;
2159*c2c66affSColin Finck 
2160*c2c66affSColin Finck         hres = IWebBrowser2_QueryInterface(web_browser, &IID_ITargetFramePriv2, (void**)&target_frame_priv);
2161*c2c66affSColin Finck         if(SUCCEEDED(hres)) {
2162*c2c66affSColin Finck             hres = ITargetFramePriv2_AggregatedNavigation2(target_frame_priv,
2163*c2c66affSColin Finck                     HLNF_DISABLEWINDOWRESTRICTIONS|HLNF_OPENINNEWWINDOW, bind_ctx, &bsc->bsc.IBindStatusCallback_iface,
2164*c2c66affSColin Finck                     name, uri, emptyW);
2165*c2c66affSColin Finck             ITargetFramePriv2_Release(target_frame_priv);
2166*c2c66affSColin Finck 
2167*c2c66affSColin Finck             if(SUCCEEDED(hres))
2168*c2c66affSColin Finck                 hres = do_query_service((IUnknown*)web_browser, &SID_SHTMLWindow, &IID_IHTMLWindow2, (void**)&new_window);
2169*c2c66affSColin Finck         }
2170*c2c66affSColin Finck         if(FAILED(hres)) {
2171*c2c66affSColin Finck             IWebBrowser2_Quit(web_browser);
2172*c2c66affSColin Finck             IWebBrowser2_Release(web_browser);
2173*c2c66affSColin Finck         }
2174*c2c66affSColin Finck     }else {
2175*c2c66affSColin Finck         WARN("Could not create InternetExplorer instance: %08x\n", hres);
2176*c2c66affSColin Finck     }
2177*c2c66affSColin Finck 
2178*c2c66affSColin Finck     IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2179*c2c66affSColin Finck     IBindCtx_Release(bind_ctx);
2180*c2c66affSColin Finck     if(FAILED(hres))
2181*c2c66affSColin Finck         return hres;
2182*c2c66affSColin Finck 
2183*c2c66affSColin Finck     IWebBrowser2_put_Visible(web_browser, VARIANT_TRUE);
2184*c2c66affSColin Finck     IWebBrowser2_Release(web_browser);
2185*c2c66affSColin Finck 
2186*c2c66affSColin Finck     if(ret)
2187*c2c66affSColin Finck         *ret = new_window;
2188*c2c66affSColin Finck     else
2189*c2c66affSColin Finck         IHTMLWindow2_Release(new_window);
2190*c2c66affSColin Finck     return S_OK;
2191*c2c66affSColin Finck }
2192*c2c66affSColin Finck 
hlink_frame_navigate(HTMLDocument * doc,LPCWSTR url,nsChannel * nschannel,DWORD hlnf,BOOL * cancel)2193*c2c66affSColin Finck HRESULT hlink_frame_navigate(HTMLDocument *doc, LPCWSTR url, nsChannel *nschannel, DWORD hlnf, BOOL *cancel)
2194*c2c66affSColin Finck {
2195*c2c66affSColin Finck     IHlinkFrame *hlink_frame;
2196*c2c66affSColin Finck     nsChannelBSC *callback;
2197*c2c66affSColin Finck     IBindCtx *bindctx;
2198*c2c66affSColin Finck     IMoniker *mon;
2199*c2c66affSColin Finck     IHlink *hlink;
2200*c2c66affSColin Finck     HRESULT hres;
2201*c2c66affSColin Finck 
2202*c2c66affSColin Finck     *cancel = FALSE;
2203*c2c66affSColin Finck 
2204*c2c66affSColin Finck     hres = do_query_service((IUnknown*)doc->doc_obj->client, &IID_IHlinkFrame, &IID_IHlinkFrame,
2205*c2c66affSColin Finck             (void**)&hlink_frame);
2206*c2c66affSColin Finck     if(FAILED(hres))
2207*c2c66affSColin Finck         return S_OK;
2208*c2c66affSColin Finck 
2209*c2c66affSColin Finck     hres = create_channelbsc(NULL, NULL, NULL, 0, FALSE, &callback);
2210*c2c66affSColin Finck     if(FAILED(hres)) {
2211*c2c66affSColin Finck         IHlinkFrame_Release(hlink_frame);
2212*c2c66affSColin Finck         return hres;
2213*c2c66affSColin Finck     }
2214*c2c66affSColin Finck 
2215*c2c66affSColin Finck     if(nschannel)
2216*c2c66affSColin Finck         read_post_data_stream(nschannel->post_data_stream, nschannel->post_data_contains_headers,
2217*c2c66affSColin Finck                 &nschannel->request_headers, &callback->bsc.request_data);
2218*c2c66affSColin Finck 
2219*c2c66affSColin Finck     hres = CreateAsyncBindCtx(0, &callback->bsc.IBindStatusCallback_iface, NULL, &bindctx);
2220*c2c66affSColin Finck     if(SUCCEEDED(hres))
2221*c2c66affSColin Finck        hres = CoCreateInstance(&CLSID_StdHlink, NULL, CLSCTX_INPROC_SERVER,
2222*c2c66affSColin Finck                 &IID_IHlink, (LPVOID*)&hlink);
2223*c2c66affSColin Finck 
2224*c2c66affSColin Finck     if(SUCCEEDED(hres))
2225*c2c66affSColin Finck         hres = CreateURLMoniker(NULL, url, &mon);
2226*c2c66affSColin Finck 
2227*c2c66affSColin Finck     if(SUCCEEDED(hres)) {
2228*c2c66affSColin Finck         IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET, mon, NULL);
2229*c2c66affSColin Finck 
2230*c2c66affSColin Finck         if(hlnf & HLNF_OPENINNEWWINDOW) {
2231*c2c66affSColin Finck             static const WCHAR wszBlank[] = {'_','b','l','a','n','k',0};
2232*c2c66affSColin Finck             IHlink_SetTargetFrameName(hlink, wszBlank); /* FIXME */
2233*c2c66affSColin Finck         }
2234*c2c66affSColin Finck 
2235*c2c66affSColin Finck         hres = IHlinkFrame_Navigate(hlink_frame, hlnf, bindctx,
2236*c2c66affSColin Finck                 &callback->bsc.IBindStatusCallback_iface, hlink);
2237*c2c66affSColin Finck         IMoniker_Release(mon);
2238*c2c66affSColin Finck         *cancel = hres == S_OK;
2239*c2c66affSColin Finck         hres = S_OK;
2240*c2c66affSColin Finck     }
2241*c2c66affSColin Finck 
2242*c2c66affSColin Finck     IHlinkFrame_Release(hlink_frame);
2243*c2c66affSColin Finck     IBindCtx_Release(bindctx);
2244*c2c66affSColin Finck     IBindStatusCallback_Release(&callback->bsc.IBindStatusCallback_iface);
2245*c2c66affSColin Finck     return hres;
2246*c2c66affSColin Finck }
2247*c2c66affSColin Finck 
navigate_uri(HTMLOuterWindow * window,IUri * uri,const WCHAR * display_uri,const request_data_t * request_data,DWORD flags)2248*c2c66affSColin Finck static HRESULT navigate_uri(HTMLOuterWindow *window, IUri *uri, const WCHAR *display_uri, const request_data_t *request_data,
2249*c2c66affSColin Finck         DWORD flags)
2250*c2c66affSColin Finck {
2251*c2c66affSColin Finck     nsWineURI *nsuri;
2252*c2c66affSColin Finck     HRESULT hres;
2253*c2c66affSColin Finck 
2254*c2c66affSColin Finck     TRACE("%s\n", debugstr_w(display_uri));
2255*c2c66affSColin Finck 
2256*c2c66affSColin Finck     if(window->doc_obj && window->doc_obj->webbrowser) {
2257*c2c66affSColin Finck         DWORD post_data_len = request_data ? request_data->post_data_len : 0;
2258*c2c66affSColin Finck         void *post_data = post_data_len ? request_data->post_data : NULL;
2259*c2c66affSColin Finck         const WCHAR *headers = request_data ? request_data->headers : NULL;
2260*c2c66affSColin Finck 
2261*c2c66affSColin Finck         if(!(flags & BINDING_REFRESH)) {
2262*c2c66affSColin Finck             BSTR frame_name = NULL;
2263*c2c66affSColin Finck             BOOL cancel = FALSE;
2264*c2c66affSColin Finck 
2265*c2c66affSColin Finck             if(window != window->doc_obj->basedoc.window) {
2266*c2c66affSColin Finck                 hres = IHTMLWindow2_get_name(&window->base.IHTMLWindow2_iface, &frame_name);
2267*c2c66affSColin Finck                 if(FAILED(hres))
2268*c2c66affSColin Finck                     return hres;
2269*c2c66affSColin Finck             }
2270*c2c66affSColin Finck 
2271*c2c66affSColin Finck             hres = IDocObjectService_FireBeforeNavigate2(window->doc_obj->doc_object_service, NULL, display_uri, 0x40,
2272*c2c66affSColin Finck                     frame_name, post_data, post_data_len ? post_data_len+1 : 0, headers, TRUE, &cancel);
2273*c2c66affSColin Finck             SysFreeString(frame_name);
2274*c2c66affSColin Finck             if(SUCCEEDED(hres) && cancel) {
2275*c2c66affSColin Finck                 TRACE("Navigation canceled\n");
2276*c2c66affSColin Finck                 return S_OK;
2277*c2c66affSColin Finck             }
2278*c2c66affSColin Finck         }
2279*c2c66affSColin Finck 
2280*c2c66affSColin Finck         if(window == window->doc_obj->basedoc.window)
2281*c2c66affSColin Finck             return super_navigate(window, uri, flags, headers, post_data, post_data_len);
2282*c2c66affSColin Finck     }
2283*c2c66affSColin Finck 
2284*c2c66affSColin Finck     if(window->doc_obj && window == window->doc_obj->basedoc.window) {
2285*c2c66affSColin Finck         BOOL cancel;
2286*c2c66affSColin Finck 
2287*c2c66affSColin Finck         hres = hlink_frame_navigate(&window->base.inner_window->doc->basedoc, display_uri, NULL, 0, &cancel);
2288*c2c66affSColin Finck         if(FAILED(hres))
2289*c2c66affSColin Finck             return hres;
2290*c2c66affSColin Finck 
2291*c2c66affSColin Finck         if(cancel) {
2292*c2c66affSColin Finck             TRACE("Navigation handled by hlink frame\n");
2293*c2c66affSColin Finck             return S_OK;
2294*c2c66affSColin Finck         }
2295*c2c66affSColin Finck     }
2296*c2c66affSColin Finck 
2297*c2c66affSColin Finck     hres = create_doc_uri(window, uri, &nsuri);
2298*c2c66affSColin Finck     if(FAILED(hres))
2299*c2c66affSColin Finck         return hres;
2300*c2c66affSColin Finck 
2301*c2c66affSColin Finck     hres = load_nsuri(window, nsuri, request_data ? request_data->post_stream : NULL, NULL, LOAD_FLAGS_NONE);
2302*c2c66affSColin Finck     nsISupports_Release((nsISupports*)nsuri);
2303*c2c66affSColin Finck     return hres;
2304*c2c66affSColin Finck }
2305*c2c66affSColin Finck 
load_uri(HTMLOuterWindow * window,IUri * uri,DWORD flags)2306*c2c66affSColin Finck HRESULT load_uri(HTMLOuterWindow *window, IUri *uri, DWORD flags)
2307*c2c66affSColin Finck {
2308*c2c66affSColin Finck     BSTR display_uri;
2309*c2c66affSColin Finck     HRESULT hres;
2310*c2c66affSColin Finck 
2311*c2c66affSColin Finck     hres = IUri_GetDisplayUri(uri, &display_uri);
2312*c2c66affSColin Finck     if(FAILED(hres))
2313*c2c66affSColin Finck         return hres;
2314*c2c66affSColin Finck 
2315*c2c66affSColin Finck     hres = navigate_uri(window, uri, display_uri, NULL, flags);
2316*c2c66affSColin Finck     SysFreeString(display_uri);
2317*c2c66affSColin Finck     return hres;
2318*c2c66affSColin Finck }
2319*c2c66affSColin Finck 
translate_uri(HTMLOuterWindow * window,IUri * orig_uri,BSTR * ret_display_uri,IUri ** ret_uri)2320*c2c66affSColin Finck static HRESULT translate_uri(HTMLOuterWindow *window, IUri *orig_uri, BSTR *ret_display_uri, IUri **ret_uri)
2321*c2c66affSColin Finck {
2322*c2c66affSColin Finck     IUri *uri = NULL;
2323*c2c66affSColin Finck     BSTR display_uri;
2324*c2c66affSColin Finck     HRESULT hres;
2325*c2c66affSColin Finck 
2326*c2c66affSColin Finck     hres = IUri_GetDisplayUri(orig_uri, &display_uri);
2327*c2c66affSColin Finck     if(FAILED(hres))
2328*c2c66affSColin Finck         return hres;
2329*c2c66affSColin Finck 
2330*c2c66affSColin Finck     if(window->doc_obj && window->doc_obj->hostui) {
2331*c2c66affSColin Finck         OLECHAR *translated_url = NULL;
2332*c2c66affSColin Finck 
2333*c2c66affSColin Finck         hres = IDocHostUIHandler_TranslateUrl(window->doc_obj->hostui, 0, display_uri,
2334*c2c66affSColin Finck                 &translated_url);
2335*c2c66affSColin Finck         if(hres == S_OK && translated_url) {
2336*c2c66affSColin Finck             TRACE("%08x %s -> %s\n", hres, debugstr_w(display_uri), debugstr_w(translated_url));
2337*c2c66affSColin Finck             SysFreeString(display_uri);
2338*c2c66affSColin Finck             hres = create_uri(translated_url, 0, &uri);
2339*c2c66affSColin Finck             CoTaskMemFree(translated_url);
2340*c2c66affSColin Finck             if(FAILED(hres))
2341*c2c66affSColin Finck                 return hres;
2342*c2c66affSColin Finck 
2343*c2c66affSColin Finck             hres = IUri_GetDisplayUri(uri, &display_uri);
2344*c2c66affSColin Finck             if(FAILED(hres)) {
2345*c2c66affSColin Finck                 IUri_Release(uri);
2346*c2c66affSColin Finck                 return hres;
2347*c2c66affSColin Finck             }
2348*c2c66affSColin Finck         }
2349*c2c66affSColin Finck     }
2350*c2c66affSColin Finck 
2351*c2c66affSColin Finck     if(!uri) {
2352*c2c66affSColin Finck         IUri_AddRef(orig_uri);
2353*c2c66affSColin Finck         uri = orig_uri;
2354*c2c66affSColin Finck     }
2355*c2c66affSColin Finck 
2356*c2c66affSColin Finck     *ret_display_uri = display_uri;
2357*c2c66affSColin Finck     *ret_uri = uri;
2358*c2c66affSColin Finck     return S_OK;
2359*c2c66affSColin Finck }
2360*c2c66affSColin Finck 
submit_form(HTMLOuterWindow * window,const WCHAR * target,IUri * submit_uri,nsIInputStream * post_stream)2361*c2c66affSColin Finck HRESULT submit_form(HTMLOuterWindow *window, const WCHAR *target, IUri *submit_uri, nsIInputStream *post_stream)
2362*c2c66affSColin Finck {
2363*c2c66affSColin Finck     request_data_t request_data = {NULL};
2364*c2c66affSColin Finck     HRESULT hres;
2365*c2c66affSColin Finck 
2366*c2c66affSColin Finck     hres = read_post_data_stream(post_stream, TRUE, NULL, &request_data);
2367*c2c66affSColin Finck     if(FAILED(hres))
2368*c2c66affSColin Finck         return hres;
2369*c2c66affSColin Finck 
2370*c2c66affSColin Finck     if(window) {
2371*c2c66affSColin Finck         IUri *uri;
2372*c2c66affSColin Finck         BSTR display_uri;
2373*c2c66affSColin Finck 
2374*c2c66affSColin Finck         window->readystate_locked++;
2375*c2c66affSColin Finck 
2376*c2c66affSColin Finck         hres = translate_uri(window, submit_uri, &display_uri, &uri);
2377*c2c66affSColin Finck         if(SUCCEEDED(hres)) {
2378*c2c66affSColin Finck             hres = navigate_uri(window, uri, display_uri, &request_data, BINDING_NAVIGATED|BINDING_SUBMIT);
2379*c2c66affSColin Finck             IUri_Release(uri);
2380*c2c66affSColin Finck             SysFreeString(display_uri);
2381*c2c66affSColin Finck         }
2382*c2c66affSColin Finck 
2383*c2c66affSColin Finck         window->readystate_locked--;
2384*c2c66affSColin Finck     }else
2385*c2c66affSColin Finck         hres = navigate_new_window(window, submit_uri, target, &request_data, NULL);
2386*c2c66affSColin Finck 
2387*c2c66affSColin Finck     release_request_data(&request_data);
2388*c2c66affSColin Finck     return hres;
2389*c2c66affSColin Finck }
2390*c2c66affSColin Finck 
navigate_url(HTMLOuterWindow * window,const WCHAR * new_url,IUri * base_uri,DWORD flags)2391*c2c66affSColin Finck HRESULT navigate_url(HTMLOuterWindow *window, const WCHAR *new_url, IUri *base_uri, DWORD flags)
2392*c2c66affSColin Finck {
2393*c2c66affSColin Finck     IUri *uri, *nav_uri;
2394*c2c66affSColin Finck     BSTR display_uri;
2395*c2c66affSColin Finck     HRESULT hres;
2396*c2c66affSColin Finck 
2397*c2c66affSColin Finck     if(new_url && base_uri)
2398*c2c66affSColin Finck         hres = CoInternetCombineUrlEx(base_uri, new_url, URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2399*c2c66affSColin Finck                 &nav_uri, 0);
2400*c2c66affSColin Finck     else
2401*c2c66affSColin Finck         hres = create_uri(new_url, 0, &nav_uri);
2402*c2c66affSColin Finck     if(FAILED(hres))
2403*c2c66affSColin Finck         return hres;
2404*c2c66affSColin Finck 
2405*c2c66affSColin Finck     hres = translate_uri(window, nav_uri, &display_uri, &uri);
2406*c2c66affSColin Finck     IUri_Release(nav_uri);
2407*c2c66affSColin Finck     if(FAILED(hres))
2408*c2c66affSColin Finck         return hres;
2409*c2c66affSColin Finck 
2410*c2c66affSColin Finck     hres = navigate_uri(window, uri, display_uri, NULL, flags);
2411*c2c66affSColin Finck     IUri_Release(uri);
2412*c2c66affSColin Finck     SysFreeString(display_uri);
2413*c2c66affSColin Finck     return hres;
2414*c2c66affSColin Finck }
2415