Commit | Line | Data |
---|---|---|
cb880d7c | 1 | /* |
920f628c | 2 | * Copyright 2006-2007 Jacek Caban for CodeWeavers |
cb880d7c JC |
3 | * |
4 | * This library is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU Lesser General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2.1 of the License, or (at your option) any later version. | |
8 | * | |
9 | * This library is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Lesser General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Lesser General Public | |
15 | * License along with this library; if not, write to the Free Software | |
360a3f91 | 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
cb880d7c JC |
17 | */ |
18 | ||
19 | #include "config.h" | |
20 | ||
21 | #include <stdarg.h> | |
cb880d7c JC |
22 | |
23 | #define COBJMACROS | |
24 | #define NONAMELESSUNION | |
25 | #define NONAMELESSSTRUCT | |
26 | ||
27 | #include "windef.h" | |
28 | #include "winbase.h" | |
29 | #include "winuser.h" | |
30 | #include "ole2.h" | |
24b1b2bc | 31 | #include "hlguids.h" |
f309cdf7 | 32 | #include "shlguid.h" |
cb880d7c JC |
33 | |
34 | #include "wine/debug.h" | |
35 | #include "wine/unicode.h" | |
36 | ||
37 | #include "mshtml_private.h" | |
38 | ||
39 | WINE_DEFAULT_DEBUG_CHANNEL(mshtml); | |
40 | ||
41 | #define CONTENT_LENGTH "Content-Length" | |
58a261b7 | 42 | #define UTF16_STR "utf-16" |
cb880d7c | 43 | |
a7caae95 JC |
44 | typedef struct { |
45 | const nsIInputStreamVtbl *lpInputStreamVtbl; | |
46 | ||
47 | LONG ref; | |
48 | ||
49 | char buf[1024]; | |
50 | DWORD buf_size; | |
51 | } nsProtocolStream; | |
52 | ||
93fe34ee JC |
53 | #define NSINSTREAM(x) ((nsIInputStream*) &(x)->lpInputStreamVtbl) |
54 | ||
c8bb048b JC |
55 | typedef struct { |
56 | void (*destroy)(BSCallback*); | |
57 | HRESULT (*start_binding)(BSCallback*); | |
58 | HRESULT (*stop_binding)(BSCallback*,HRESULT); | |
59 | HRESULT (*read_data)(BSCallback*,IStream*); | |
60 | HRESULT (*on_progress)(BSCallback*,ULONG,LPCWSTR); | |
61 | } BSCallbackVtbl; | |
62 | ||
a7caae95 JC |
63 | struct BSCallback { |
64 | const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl; | |
65 | const IServiceProviderVtbl *lpServiceProviderVtbl; | |
66 | const IHttpNegotiate2Vtbl *lpHttpNegotiate2Vtbl; | |
67 | const IInternetBindInfoVtbl *lpInternetBindInfoVtbl; | |
68 | ||
c8bb048b JC |
69 | const BSCallbackVtbl *vtbl; |
70 | ||
a7caae95 JC |
71 | LONG ref; |
72 | ||
73 | LPWSTR headers; | |
74 | HGLOBAL post_data; | |
75 | ULONG post_data_len; | |
76 | ULONG readed; | |
c8bb048b | 77 | DWORD bindf; |
a7caae95 JC |
78 | |
79 | IMoniker *mon; | |
80 | IBinding *binding; | |
81 | ||
82 | HTMLDocument *doc; | |
83 | ||
a7caae95 JC |
84 | struct list entry; |
85 | }; | |
86 | ||
93fe34ee JC |
87 | #define NSINSTREAM_THIS(iface) DEFINE_THIS(nsProtocolStream, InputStream, iface) |
88 | ||
89 | static nsresult NSAPI nsInputStream_QueryInterface(nsIInputStream *iface, nsIIDRef riid, | |
90 | nsQIResult result) | |
91 | { | |
92 | nsProtocolStream *This = NSINSTREAM_THIS(iface); | |
93 | ||
94 | *result = NULL; | |
95 | ||
96 | if(IsEqualGUID(&IID_nsISupports, riid)) { | |
97 | TRACE("(%p)->(IID_nsISupports %p)\n", This, result); | |
98 | *result = NSINSTREAM(This); | |
99 | }else if(IsEqualGUID(&IID_nsIInputStream, riid)) { | |
100 | TRACE("(%p)->(IID_nsIInputStream %p)\n", This, result); | |
101 | *result = NSINSTREAM(This); | |
102 | } | |
103 | ||
104 | if(*result) { | |
105 | nsIInputStream_AddRef(NSINSTREAM(This)); | |
106 | return NS_OK; | |
107 | } | |
108 | ||
109 | WARN("unsupported interface %s\n", debugstr_guid(riid)); | |
110 | return NS_NOINTERFACE; | |
111 | } | |
112 | ||
113 | static nsrefcnt NSAPI nsInputStream_AddRef(nsIInputStream *iface) | |
114 | { | |
115 | nsProtocolStream *This = NSINSTREAM_THIS(iface); | |
116 | LONG ref = InterlockedIncrement(&This->ref); | |
117 | ||
0c74c0a9 | 118 | TRACE("(%p) ref=%d\n", This, ref); |
93fe34ee JC |
119 | |
120 | return ref; | |
121 | } | |
122 | ||
123 | ||
124 | static nsrefcnt NSAPI nsInputStream_Release(nsIInputStream *iface) | |
125 | { | |
126 | nsProtocolStream *This = NSINSTREAM_THIS(iface); | |
127 | LONG ref = InterlockedDecrement(&This->ref); | |
128 | ||
0c74c0a9 | 129 | TRACE("(%p) ref=%d\n", This, ref); |
93fe34ee JC |
130 | |
131 | if(!ref) | |
a084d1db | 132 | heap_free(This); |
93fe34ee JC |
133 | |
134 | return ref; | |
135 | } | |
136 | ||
137 | static nsresult NSAPI nsInputStream_Close(nsIInputStream *iface) | |
138 | { | |
139 | nsProtocolStream *This = NSINSTREAM_THIS(iface); | |
140 | FIXME("(%p)\n", This); | |
141 | return NS_ERROR_NOT_IMPLEMENTED; | |
142 | } | |
143 | ||
144 | static nsresult NSAPI nsInputStream_Available(nsIInputStream *iface, PRUint32 *_retval) | |
145 | { | |
146 | nsProtocolStream *This = NSINSTREAM_THIS(iface); | |
147 | FIXME("(%p)->(%p)\n", This, _retval); | |
148 | return NS_ERROR_NOT_IMPLEMENTED; | |
149 | } | |
150 | ||
151 | static nsresult NSAPI nsInputStream_Read(nsIInputStream *iface, char *aBuf, PRUint32 aCount, | |
152 | PRUint32 *_retval) | |
153 | { | |
154 | nsProtocolStream *This = NSINSTREAM_THIS(iface); | |
0fbb175d | 155 | |
0c74c0a9 | 156 | TRACE("(%p)->(%p %d %p)\n", This, aBuf, aCount, _retval); |
0fbb175d JC |
157 | |
158 | /* Gecko always calls Read with big enough buffer */ | |
159 | if(aCount < This->buf_size) | |
160 | FIXME("aCount < This->buf_size\n"); | |
161 | ||
162 | *_retval = This->buf_size; | |
163 | if(This->buf_size) | |
164 | memcpy(aBuf, This->buf, This->buf_size); | |
165 | This->buf_size = 0; | |
166 | ||
167 | return NS_OK; | |
93fe34ee JC |
168 | } |
169 | ||
170 | static nsresult NSAPI nsInputStream_ReadSegments(nsIInputStream *iface, | |
12286afc | 171 | nsresult (WINAPI *aWriter)(nsIInputStream*,void*,const char*,PRUint32,PRUint32,PRUint32*), |
93fe34ee JC |
172 | void *aClousure, PRUint32 aCount, PRUint32 *_retval) |
173 | { | |
174 | nsProtocolStream *This = NSINSTREAM_THIS(iface); | |
175 | PRUint32 written = 0; | |
176 | nsresult nsres; | |
177 | ||
0c74c0a9 | 178 | TRACE("(%p)->(%p %p %d %p)\n", This, aWriter, aClousure, aCount, _retval); |
93fe34ee JC |
179 | |
180 | if(!This->buf_size) | |
181 | return S_OK; | |
182 | ||
183 | if(This->buf_size > aCount) | |
184 | FIXME("buf_size > aCount\n"); | |
185 | ||
186 | nsres = aWriter(NSINSTREAM(This), aClousure, This->buf, 0, This->buf_size, &written); | |
187 | if(NS_FAILED(nsres)) | |
7437cc1e JC |
188 | TRACE("aWritter failed: %08x\n", nsres); |
189 | else if(written != This->buf_size) | |
190 | FIXME("written %d != buf_size %d\n", written, This->buf_size); | |
93fe34ee JC |
191 | |
192 | This->buf_size -= written; | |
193 | ||
7437cc1e | 194 | *_retval = written; |
93fe34ee JC |
195 | return nsres; |
196 | } | |
197 | ||
198 | static nsresult NSAPI nsInputStream_IsNonBlocking(nsIInputStream *iface, PRBool *_retval) | |
199 | { | |
200 | nsProtocolStream *This = NSINSTREAM_THIS(iface); | |
201 | FIXME("(%p)->(%p)\n", This, _retval); | |
202 | return NS_ERROR_NOT_IMPLEMENTED; | |
203 | } | |
204 | ||
205 | #undef NSINSTREAM_THIS | |
206 | ||
207 | static const nsIInputStreamVtbl nsInputStreamVtbl = { | |
208 | nsInputStream_QueryInterface, | |
209 | nsInputStream_AddRef, | |
210 | nsInputStream_Release, | |
211 | nsInputStream_Close, | |
212 | nsInputStream_Available, | |
213 | nsInputStream_Read, | |
214 | nsInputStream_ReadSegments, | |
215 | nsInputStream_IsNonBlocking | |
216 | }; | |
217 | ||
98da8e28 | 218 | static nsProtocolStream *create_nsprotocol_stream(void) |
93fe34ee | 219 | { |
a084d1db | 220 | nsProtocolStream *ret = heap_alloc(sizeof(nsProtocolStream)); |
93fe34ee JC |
221 | |
222 | ret->lpInputStreamVtbl = &nsInputStreamVtbl; | |
223 | ret->ref = 1; | |
224 | ret->buf_size = 0; | |
225 | ||
226 | return ret; | |
227 | } | |
228 | ||
cb880d7c JC |
229 | #define STATUSCLB_THIS(iface) DEFINE_THIS(BSCallback, BindStatusCallback, iface) |
230 | ||
cb880d7c JC |
231 | static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, |
232 | REFIID riid, void **ppv) | |
233 | { | |
234 | BSCallback *This = STATUSCLB_THIS(iface); | |
235 | ||
236 | *ppv = NULL; | |
237 | if(IsEqualGUID(&IID_IUnknown, riid)) { | |
238 | TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv); | |
239 | *ppv = STATUSCLB(This); | |
240 | }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) { | |
241 | TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv); | |
242 | *ppv = STATUSCLB(This); | |
243 | }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { | |
244 | TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); | |
245 | *ppv = SERVPROV(This); | |
246 | }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) { | |
247 | TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv); | |
248 | *ppv = HTTPNEG(This); | |
249 | }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) { | |
250 | TRACE("(%p)->(IID_IHttpNegotiate2 %p)\n", This, ppv); | |
251 | *ppv = HTTPNEG(This); | |
252 | }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) { | |
253 | TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv); | |
254 | *ppv = BINDINFO(This); | |
255 | } | |
256 | ||
257 | if(*ppv) { | |
258 | IBindStatusCallback_AddRef(STATUSCLB(This)); | |
259 | return S_OK; | |
260 | } | |
261 | ||
262 | TRACE("Unsupported riid = %s\n", debugstr_guid(riid)); | |
263 | return E_NOINTERFACE; | |
264 | } | |
265 | ||
266 | static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface) | |
267 | { | |
268 | BSCallback *This = STATUSCLB_THIS(iface); | |
269 | LONG ref = InterlockedIncrement(&This->ref); | |
270 | ||
0c74c0a9 | 271 | TRACE("(%p) ref = %d\n", This, ref); |
cb880d7c JC |
272 | |
273 | return ref; | |
274 | } | |
275 | ||
276 | static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface) | |
277 | { | |
278 | BSCallback *This = STATUSCLB_THIS(iface); | |
279 | LONG ref = InterlockedDecrement(&This->ref); | |
280 | ||
0c74c0a9 | 281 | TRACE("(%p) ref = %d\n", This, ref); |
cb880d7c JC |
282 | |
283 | if(!ref) { | |
284 | if(This->post_data) | |
285 | GlobalFree(This->post_data); | |
aa760c8b JC |
286 | if(This->mon) |
287 | IMoniker_Release(This->mon); | |
7f107fb8 JC |
288 | if(This->binding) |
289 | IBinding_Release(This->binding); | |
f309cdf7 | 290 | list_remove(&This->entry); |
a084d1db | 291 | heap_free(This->headers); |
c8bb048b JC |
292 | |
293 | This->vtbl->destroy(This); | |
cb880d7c JC |
294 | } |
295 | ||
296 | return ref; | |
297 | } | |
298 | ||
299 | static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, | |
300 | DWORD dwReserved, IBinding *pbind) | |
301 | { | |
302 | BSCallback *This = STATUSCLB_THIS(iface); | |
7f107fb8 | 303 | |
0c74c0a9 | 304 | TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind); |
7f107fb8 JC |
305 | |
306 | IBinding_AddRef(pbind); | |
307 | This->binding = pbind; | |
308 | ||
f309cdf7 JC |
309 | if(This->doc) |
310 | list_add_head(&This->doc->bindings, &This->entry); | |
311 | ||
c8bb048b | 312 | return This->vtbl->start_binding(This); |
cb880d7c JC |
313 | } |
314 | ||
315 | static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) | |
316 | { | |
317 | BSCallback *This = STATUSCLB_THIS(iface); | |
318 | FIXME("(%p)->(%p)\n", This, pnPriority); | |
319 | return E_NOTIMPL; | |
320 | } | |
321 | ||
322 | static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved) | |
323 | { | |
324 | BSCallback *This = STATUSCLB_THIS(iface); | |
0c74c0a9 | 325 | FIXME("(%p)->(%d)\n", This, reserved); |
cb880d7c JC |
326 | return E_NOTIMPL; |
327 | } | |
328 | ||
329 | static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, | |
330 | ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) | |
331 | { | |
332 | BSCallback *This = STATUSCLB_THIS(iface); | |
56bb0286 | 333 | |
0c74c0a9 | 334 | TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, |
cb880d7c | 335 | debugstr_w(szStatusText)); |
56bb0286 | 336 | |
c8bb048b | 337 | return This->vtbl->on_progress(This, ulStatusCode, szStatusText); |
cb880d7c JC |
338 | } |
339 | ||
340 | static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, | |
341 | HRESULT hresult, LPCWSTR szError) | |
342 | { | |
343 | BSCallback *This = STATUSCLB_THIS(iface); | |
78c287f1 | 344 | |
0c74c0a9 | 345 | TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError)); |
78c287f1 | 346 | |
94a264d0 JC |
347 | if(This->binding) { |
348 | IBinding_Release(This->binding); | |
349 | This->binding = NULL; | |
350 | } | |
7f107fb8 | 351 | |
f309cdf7 JC |
352 | list_remove(&This->entry); |
353 | ||
c8bb048b | 354 | return This->vtbl->stop_binding(This, hresult); |
cb880d7c JC |
355 | } |
356 | ||
357 | static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, | |
358 | DWORD *grfBINDF, BINDINFO *pbindinfo) | |
359 | { | |
360 | BSCallback *This = STATUSCLB_THIS(iface); | |
361 | DWORD size; | |
362 | ||
363 | TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); | |
364 | ||
c8bb048b | 365 | *grfBINDF = This->bindf; |
cb880d7c JC |
366 | |
367 | size = pbindinfo->cbSize; | |
368 | memset(pbindinfo, 0, size); | |
369 | pbindinfo->cbSize = size; | |
370 | ||
dc0cfe77 | 371 | pbindinfo->cbstgmedData = This->post_data_len; |
cb880d7c | 372 | pbindinfo->dwCodePage = CP_UTF8; |
e15b5c70 | 373 | pbindinfo->dwOptions = 0x80000; |
cb880d7c JC |
374 | |
375 | if(This->post_data) { | |
376 | pbindinfo->dwBindVerb = BINDVERB_POST; | |
377 | ||
378 | pbindinfo->stgmedData.tymed = TYMED_HGLOBAL; | |
379 | pbindinfo->stgmedData.u.hGlobal = This->post_data; | |
380 | pbindinfo->stgmedData.pUnkForRelease = (IUnknown*)STATUSCLB(This); | |
381 | IBindStatusCallback_AddRef(STATUSCLB(This)); | |
382 | } | |
383 | ||
384 | return S_OK; | |
385 | } | |
386 | ||
387 | static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, | |
388 | DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) | |
389 | { | |
390 | BSCallback *This = STATUSCLB_THIS(iface); | |
93fe34ee | 391 | |
0c74c0a9 | 392 | TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed); |
93fe34ee | 393 | |
c8bb048b | 394 | return This->vtbl->read_data(This, pstgmed->u.pstm); |
cb880d7c JC |
395 | } |
396 | ||
397 | static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, | |
398 | REFIID riid, IUnknown *punk) | |
399 | { | |
400 | BSCallback *This = STATUSCLB_THIS(iface); | |
401 | FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk); | |
402 | return E_NOTIMPL; | |
403 | } | |
404 | ||
405 | #undef STATUSCLB_THIS | |
406 | ||
407 | static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = { | |
408 | BindStatusCallback_QueryInterface, | |
409 | BindStatusCallback_AddRef, | |
410 | BindStatusCallback_Release, | |
411 | BindStatusCallback_OnStartBinding, | |
412 | BindStatusCallback_GetPriority, | |
413 | BindStatusCallback_OnLowResource, | |
414 | BindStatusCallback_OnProgress, | |
415 | BindStatusCallback_OnStopBinding, | |
416 | BindStatusCallback_GetBindInfo, | |
417 | BindStatusCallback_OnDataAvailable, | |
418 | BindStatusCallback_OnObjectAvailable | |
419 | }; | |
420 | ||
421 | #define HTTPNEG_THIS(iface) DEFINE_THIS(BSCallback, HttpNegotiate2, iface) | |
422 | ||
423 | static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, | |
424 | REFIID riid, void **ppv) | |
425 | { | |
426 | BSCallback *This = HTTPNEG_THIS(iface); | |
427 | return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); | |
428 | } | |
429 | ||
430 | static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface) | |
431 | { | |
432 | BSCallback *This = HTTPNEG_THIS(iface); | |
433 | return IBindStatusCallback_AddRef(STATUSCLB(This)); | |
434 | } | |
435 | ||
436 | static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface) | |
437 | { | |
438 | BSCallback *This = HTTPNEG_THIS(iface); | |
439 | return IBindStatusCallback_Release(STATUSCLB(This)); | |
440 | } | |
441 | ||
442 | static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, | |
443 | LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) | |
444 | { | |
445 | BSCallback *This = HTTPNEG_THIS(iface); | |
446 | DWORD size; | |
447 | ||
0c74c0a9 | 448 | TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), |
cb880d7c JC |
449 | dwReserved, pszAdditionalHeaders); |
450 | ||
451 | if(!This->headers) { | |
452 | *pszAdditionalHeaders = NULL; | |
453 | return S_OK; | |
454 | } | |
455 | ||
456 | size = (strlenW(This->headers)+1)*sizeof(WCHAR); | |
457 | *pszAdditionalHeaders = CoTaskMemAlloc(size); | |
458 | memcpy(*pszAdditionalHeaders, This->headers, size); | |
459 | ||
460 | return S_OK; | |
461 | } | |
462 | ||
463 | static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode, | |
464 | LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) | |
465 | { | |
466 | BSCallback *This = HTTPNEG_THIS(iface); | |
0c74c0a9 | 467 | FIXME("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders), |
cb880d7c JC |
468 | debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders); |
469 | return E_NOTIMPL; | |
470 | } | |
471 | ||
472 | static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface, | |
473 | BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved) | |
474 | { | |
475 | BSCallback *This = HTTPNEG_THIS(iface); | |
476 | FIXME("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved); | |
477 | return E_NOTIMPL; | |
478 | } | |
479 | ||
480 | #undef HTTPNEG | |
481 | ||
482 | static const IHttpNegotiate2Vtbl HttpNegotiate2Vtbl = { | |
483 | HttpNegotiate_QueryInterface, | |
484 | HttpNegotiate_AddRef, | |
485 | HttpNegotiate_Release, | |
486 | HttpNegotiate_BeginningTransaction, | |
487 | HttpNegotiate_OnResponse, | |
488 | HttpNegotiate_GetRootSecurityId | |
489 | }; | |
490 | ||
491 | #define BINDINFO_THIS(iface) DEFINE_THIS(BSCallback, InternetBindInfo, iface) | |
492 | ||
493 | static HRESULT WINAPI InternetBindInfo_QueryInterface(IInternetBindInfo *iface, | |
494 | REFIID riid, void **ppv) | |
495 | { | |
496 | BSCallback *This = BINDINFO_THIS(iface); | |
497 | return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); | |
498 | } | |
499 | ||
500 | static ULONG WINAPI InternetBindInfo_AddRef(IInternetBindInfo *iface) | |
501 | { | |
502 | BSCallback *This = BINDINFO_THIS(iface); | |
503 | return IBindStatusCallback_AddRef(STATUSCLB(This)); | |
504 | } | |
505 | ||
506 | static ULONG WINAPI InternetBindInfo_Release(IInternetBindInfo *iface) | |
507 | { | |
508 | BSCallback *This = BINDINFO_THIS(iface); | |
509 | return IBindStatusCallback_Release(STATUSCLB(This)); | |
510 | } | |
511 | ||
512 | static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface, | |
513 | DWORD *grfBINDF, BINDINFO *pbindinfo) | |
514 | { | |
515 | BSCallback *This = BINDINFO_THIS(iface); | |
516 | FIXME("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); | |
517 | return E_NOTIMPL; | |
518 | } | |
519 | ||
520 | static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface, | |
521 | ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched) | |
522 | { | |
523 | BSCallback *This = BINDINFO_THIS(iface); | |
0c74c0a9 | 524 | FIXME("(%p)->(%u %p %u %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched); |
cb880d7c JC |
525 | return E_NOTIMPL; |
526 | } | |
527 | ||
528 | #undef BINDINFO_THIS | |
529 | ||
530 | static const IInternetBindInfoVtbl InternetBindInfoVtbl = { | |
531 | InternetBindInfo_QueryInterface, | |
532 | InternetBindInfo_AddRef, | |
533 | InternetBindInfo_Release, | |
534 | InternetBindInfo_GetBindInfo, | |
535 | InternetBindInfo_GetBindString | |
536 | }; | |
537 | ||
538 | #define SERVPROV_THIS(iface) DEFINE_THIS(BSCallback, ServiceProvider, iface) | |
539 | ||
540 | static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface, | |
541 | REFIID riid, void **ppv) | |
542 | { | |
543 | BSCallback *This = SERVPROV_THIS(iface); | |
544 | return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); | |
545 | } | |
546 | ||
547 | static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface) | |
548 | { | |
549 | BSCallback *This = SERVPROV_THIS(iface); | |
550 | return IBindStatusCallback_AddRef(STATUSCLB(This)); | |
551 | } | |
552 | ||
553 | static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface) | |
554 | { | |
555 | BSCallback *This = SERVPROV_THIS(iface); | |
556 | return IBindStatusCallback_Release(STATUSCLB(This)); | |
557 | } | |
558 | ||
559 | static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface, | |
560 | REFGUID guidService, REFIID riid, void **ppv) | |
561 | { | |
562 | BSCallback *This = SERVPROV_THIS(iface); | |
b61bc4b9 JC |
563 | TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); |
564 | return E_NOINTERFACE; | |
cb880d7c JC |
565 | } |
566 | ||
567 | #undef SERVPROV_THIS | |
568 | ||
569 | static const IServiceProviderVtbl ServiceProviderVtbl = { | |
570 | BSCServiceProvider_QueryInterface, | |
571 | BSCServiceProvider_AddRef, | |
572 | BSCServiceProvider_Release, | |
573 | BSCServiceProvider_QueryService | |
574 | }; | |
575 | ||
c8bb048b | 576 | static void init_bscallback(BSCallback *This, const BSCallbackVtbl *vtbl, IMoniker *mon, DWORD bindf) |
cb880d7c | 577 | { |
c8bb048b JC |
578 | This->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl; |
579 | This->lpServiceProviderVtbl = &ServiceProviderVtbl; | |
580 | This->lpHttpNegotiate2Vtbl = &HttpNegotiate2Vtbl; | |
581 | This->lpInternetBindInfoVtbl = &InternetBindInfoVtbl; | |
582 | This->vtbl = vtbl; | |
583 | This->ref = 1; | |
584 | This->bindf = bindf; | |
cb880d7c | 585 | |
c8bb048b | 586 | list_init(&This->entry); |
f309cdf7 | 587 | |
aa760c8b JC |
588 | if(mon) |
589 | IMoniker_AddRef(mon); | |
c8bb048b | 590 | This->mon = mon; |
cb880d7c JC |
591 | } |
592 | ||
57b876dd JC |
593 | /* Calls undocumented 84 cmd of CGID_ShellDocView */ |
594 | static void call_docview_84(HTMLDocument *doc) | |
595 | { | |
596 | IOleCommandTarget *olecmd; | |
597 | VARIANT var; | |
598 | HRESULT hres; | |
599 | ||
600 | if(!doc->client) | |
601 | return; | |
602 | ||
603 | hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd); | |
604 | if(FAILED(hres)) | |
605 | return; | |
606 | ||
607 | VariantInit(&var); | |
608 | hres = IOleCommandTarget_Exec(olecmd, &CGID_ShellDocView, 84, 0, NULL, &var); | |
609 | IOleCommandTarget_Release(olecmd); | |
610 | if(SUCCEEDED(hres) && V_VT(&var) != VT_NULL) | |
611 | FIXME("handle result\n"); | |
612 | } | |
613 | ||
cb880d7c JC |
614 | static void parse_post_data(nsIInputStream *post_data_stream, LPWSTR *headers_ret, |
615 | HGLOBAL *post_data_ret, ULONG *post_data_len_ret) | |
616 | { | |
617 | PRUint32 post_data_len = 0, available = 0; | |
618 | HGLOBAL post_data = NULL; | |
619 | LPWSTR headers = NULL; | |
620 | DWORD headers_len = 0, len; | |
71b881e4 | 621 | const char *ptr, *ptr2, *post_data_end; |
cb880d7c JC |
622 | |
623 | nsIInputStream_Available(post_data_stream, &available); | |
624 | post_data = GlobalAlloc(0, available+1); | |
625 | nsIInputStream_Read(post_data_stream, post_data, available, &post_data_len); | |
d2389dc0 JC |
626 | |
627 | TRACE("post_data = %s\n", debugstr_an(post_data, post_data_len)); | |
cb880d7c JC |
628 | |
629 | ptr = ptr2 = post_data; | |
71b881e4 | 630 | post_data_end = (const char*)post_data+post_data_len; |
cb880d7c | 631 | |
71b881e4 JC |
632 | while(ptr < post_data_end && (*ptr != '\r' || ptr[1] != '\n')) { |
633 | while(ptr < post_data_end && (*ptr != '\r' || ptr[1] != '\n')) | |
cb880d7c JC |
634 | ptr++; |
635 | ||
636 | if(!*ptr) { | |
637 | FIXME("*ptr = 0\n"); | |
638 | return; | |
639 | } | |
640 | ||
641 | ptr += 2; | |
642 | ||
643 | if(ptr-ptr2 >= sizeof(CONTENT_LENGTH) | |
644 | && CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, | |
645 | CONTENT_LENGTH, sizeof(CONTENT_LENGTH)-1, | |
646 | ptr2, sizeof(CONTENT_LENGTH)-1) == CSTR_EQUAL) { | |
647 | ptr2 = ptr; | |
648 | continue; | |
649 | } | |
650 | ||
651 | len = MultiByteToWideChar(CP_ACP, 0, ptr2, ptr-ptr2, NULL, 0); | |
652 | ||
653 | if(headers) | |
a084d1db | 654 | headers = heap_realloc(headers,(headers_len+len+1)*sizeof(WCHAR)); |
cb880d7c | 655 | else |
a084d1db | 656 | headers = heap_alloc((len+1)*sizeof(WCHAR)); |
cb880d7c JC |
657 | |
658 | len = MultiByteToWideChar(CP_ACP, 0, ptr2, ptr-ptr2, headers+headers_len, -1); | |
659 | headers_len += len; | |
660 | ||
661 | ptr2 = ptr; | |
662 | } | |
663 | ||
664 | headers[headers_len] = 0; | |
665 | *headers_ret = headers; | |
666 | ||
71b881e4 | 667 | if(ptr >= post_data_end-2) { |
cb880d7c JC |
668 | GlobalFree(post_data); |
669 | return; | |
670 | } | |
671 | ||
71b881e4 JC |
672 | ptr += 2; |
673 | ||
cb880d7c | 674 | if(headers_len) { |
cb880d7c | 675 | post_data_len -= ptr-(const char*)post_data; |
d2389dc0 | 676 | memmove(post_data, ptr, post_data_len); |
cb880d7c JC |
677 | post_data = GlobalReAlloc(post_data, post_data_len+1, 0); |
678 | } | |
679 | ||
cb880d7c | 680 | *post_data_ret = post_data; |
71b881e4 | 681 | *post_data_len_ret = post_data_len; |
cb880d7c JC |
682 | } |
683 | ||
82a199bc | 684 | HRESULT start_binding(HTMLDocument *doc, BSCallback *bscallback, IBindCtx *bctx) |
ee8c855f JC |
685 | { |
686 | IStream *str = NULL; | |
ee8c855f JC |
687 | HRESULT hres; |
688 | ||
f309cdf7 | 689 | bscallback->doc = doc; |
c8bb048b | 690 | call_docview_84(doc); |
f309cdf7 | 691 | |
82a199bc JC |
692 | if(bctx) { |
693 | RegisterBindStatusCallback(bctx, STATUSCLB(bscallback), NULL, 0); | |
694 | IBindCtx_AddRef(bctx); | |
695 | }else { | |
696 | hres = CreateAsyncBindCtx(0, STATUSCLB(bscallback), NULL, &bctx); | |
697 | if(FAILED(hres)) { | |
698 | WARN("CreateAsyncBindCtx failed: %08x\n", hres); | |
c8bb048b | 699 | bscallback->vtbl->stop_binding(bscallback, hres); |
82a199bc JC |
700 | return hres; |
701 | } | |
ee8c855f JC |
702 | } |
703 | ||
aa760c8b | 704 | hres = IMoniker_BindToStorage(bscallback->mon, bctx, NULL, &IID_IStream, (void**)&str); |
ee8c855f JC |
705 | IBindCtx_Release(bctx); |
706 | if(FAILED(hres)) { | |
0c74c0a9 | 707 | WARN("BindToStorage failed: %08x\n", hres); |
c8bb048b | 708 | bscallback->vtbl->stop_binding(bscallback, hres); |
ee8c855f JC |
709 | return hres; |
710 | } | |
711 | ||
712 | if(str) | |
713 | IStream_Release(str); | |
714 | ||
aa760c8b JC |
715 | IMoniker_Release(bscallback->mon); |
716 | bscallback->mon = NULL; | |
addc9957 | 717 | |
ee8c855f JC |
718 | return S_OK; |
719 | } | |
ccd33999 | 720 | |
cb7b58c5 JC |
721 | typedef struct { |
722 | BSCallback bsc; | |
723 | ||
724 | DWORD size; | |
725 | BYTE *buf; | |
726 | HRESULT hres; | |
727 | } BufferBSC; | |
728 | ||
729 | #define BUFFERBSC_THIS(bsc) ((BufferBSC*) bsc) | |
730 | ||
731 | static void BufferBSC_destroy(BSCallback *bsc) | |
732 | { | |
733 | BufferBSC *This = BUFFERBSC_THIS(bsc); | |
734 | ||
735 | heap_free(This->buf); | |
736 | heap_free(This); | |
737 | } | |
738 | ||
739 | static HRESULT BufferBSC_start_binding(BSCallback *bsc) | |
740 | { | |
741 | return S_OK; | |
742 | } | |
743 | ||
744 | static HRESULT BufferBSC_stop_binding(BSCallback *bsc, HRESULT result) | |
745 | { | |
746 | BufferBSC *This = BUFFERBSC_THIS(bsc); | |
747 | ||
748 | This->hres = result; | |
749 | ||
750 | if(FAILED(result)) { | |
751 | heap_free(This->buf); | |
752 | This->buf = NULL; | |
753 | This->size = 0; | |
754 | } | |
755 | ||
756 | return S_OK; | |
757 | } | |
758 | ||
759 | static HRESULT BufferBSC_read_data(BSCallback *bsc, IStream *stream) | |
760 | { | |
761 | BufferBSC *This = BUFFERBSC_THIS(bsc); | |
762 | DWORD readed; | |
763 | HRESULT hres; | |
764 | ||
765 | if(!This->buf) { | |
766 | This->size = 128; | |
767 | This->buf = heap_alloc(This->size); | |
768 | } | |
769 | ||
770 | do { | |
771 | if(This->bsc.readed == This->size) { | |
772 | This->size <<= 1; | |
773 | This->buf = heap_realloc(This->buf, This->size); | |
774 | } | |
775 | ||
776 | readed = 0; | |
777 | hres = IStream_Read(stream, This->buf+This->bsc.readed, This->size-This->bsc.readed, &readed); | |
778 | This->bsc.readed += readed; | |
779 | }while(hres == S_OK); | |
780 | ||
781 | return S_OK; | |
782 | } | |
783 | ||
784 | static HRESULT BufferBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR status_text) | |
785 | { | |
786 | return S_OK; | |
787 | } | |
788 | ||
789 | #undef BUFFERBSC_THIS | |
790 | ||
791 | static const BSCallbackVtbl BufferBSCVtbl = { | |
792 | BufferBSC_destroy, | |
793 | BufferBSC_start_binding, | |
794 | BufferBSC_stop_binding, | |
795 | BufferBSC_read_data, | |
796 | BufferBSC_on_progress, | |
797 | }; | |
798 | ||
799 | ||
800 | static BufferBSC *create_bufferbsc(IMoniker *mon) | |
801 | { | |
802 | BufferBSC *ret = heap_alloc_zero(sizeof(*ret)); | |
803 | ||
804 | init_bscallback(&ret->bsc, &BufferBSCVtbl, mon, 0); | |
805 | ret->hres = E_FAIL; | |
806 | ||
807 | return ret; | |
808 | } | |
809 | ||
b2c80e6b | 810 | HRESULT bind_mon_to_buffer(HTMLDocument *doc, IMoniker *mon, void **buf, DWORD *size) |
cb7b58c5 JC |
811 | { |
812 | BufferBSC *bsc = create_bufferbsc(mon); | |
813 | HRESULT hres; | |
814 | ||
815 | *buf = NULL; | |
816 | ||
817 | hres = start_binding(doc, &bsc->bsc, NULL); | |
818 | if(SUCCEEDED(hres)) { | |
819 | hres = bsc->hres; | |
820 | if(SUCCEEDED(hres)) { | |
821 | *buf = bsc->buf; | |
822 | bsc->buf = NULL; | |
b2c80e6b | 823 | *size = bsc->bsc.readed; |
cb7b58c5 JC |
824 | bsc->size = 0; |
825 | } | |
826 | } | |
827 | ||
828 | IBindStatusCallback_Release(STATUSCLB(&bsc->bsc)); | |
829 | ||
830 | return hres; | |
831 | } | |
832 | ||
c8bb048b JC |
833 | struct nsChannelBSC { |
834 | BSCallback bsc; | |
835 | ||
836 | nsChannel *nschannel; | |
837 | nsIStreamListener *nslistener; | |
838 | nsISupports *nscontext; | |
839 | ||
840 | nsProtocolStream *nsstream; | |
841 | }; | |
842 | ||
843 | static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) | |
844 | { | |
845 | nsresult nsres; | |
846 | HRESULT hres; | |
847 | ||
848 | if(!This->nslistener) { | |
849 | BYTE buf[1024]; | |
850 | DWORD read; | |
851 | ||
852 | do { | |
853 | read = 0; | |
854 | hres = IStream_Read(stream, buf, sizeof(buf), &read); | |
855 | }while(hres == S_OK && read); | |
856 | ||
857 | return S_OK; | |
858 | } | |
859 | ||
860 | if(!This->nsstream) | |
861 | This->nsstream = create_nsprotocol_stream(); | |
862 | ||
863 | do { | |
864 | hres = IStream_Read(stream, This->nsstream->buf, sizeof(This->nsstream->buf), | |
865 | &This->nsstream->buf_size); | |
866 | if(!This->nsstream->buf_size) | |
867 | break; | |
868 | ||
869 | if(!This->bsc.readed && This->nsstream->buf_size >= 2 && *(WORD*)This->nsstream->buf == 0xfeff) { | |
870 | This->nschannel->charset = heap_alloc(sizeof(UTF16_STR)); | |
871 | memcpy(This->nschannel->charset, UTF16_STR, sizeof(UTF16_STR)); | |
872 | } | |
873 | ||
874 | if(!This->bsc.readed) { | |
875 | nsres = nsIStreamListener_OnStartRequest(This->nslistener, | |
876 | (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext); | |
877 | if(NS_FAILED(nsres)) | |
878 | FIXME("OnStartRequest failed: %08x\n", nsres); | |
879 | ||
880 | /* events are reset when a new document URI is loaded, so re-initialise them here */ | |
881 | if(This->bsc.doc && This->bsc.doc->bscallback == This && This->bsc.doc->nscontainer) | |
882 | init_nsevents(This->bsc.doc->nscontainer); | |
883 | } | |
884 | ||
885 | This->bsc.readed += This->nsstream->buf_size; | |
886 | ||
887 | nsres = nsIStreamListener_OnDataAvailable(This->nslistener, | |
888 | (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext, | |
889 | NSINSTREAM(This->nsstream), This->bsc.readed-This->nsstream->buf_size, | |
890 | This->nsstream->buf_size); | |
891 | if(NS_FAILED(nsres)) | |
892 | ERR("OnDataAvailable failed: %08x\n", nsres); | |
893 | ||
894 | if(This->nsstream->buf_size) | |
895 | FIXME("buffer is not empty!\n"); | |
896 | }while(hres == S_OK); | |
897 | ||
898 | return S_OK; | |
899 | } | |
900 | ||
901 | static void on_stop_nsrequest(nsChannelBSC *This) | |
902 | { | |
903 | if(!This->nslistener) | |
904 | return; | |
905 | ||
906 | nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel), | |
907 | This->nscontext, NS_OK); | |
908 | } | |
909 | ||
910 | static void add_nsrequest(nsChannelBSC *This) | |
911 | { | |
912 | nsresult nsres; | |
913 | ||
914 | if(!This->nschannel || !This->nschannel->load_group) | |
915 | return; | |
916 | ||
917 | nsres = nsILoadGroup_AddRequest(This->nschannel->load_group, | |
918 | (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext); | |
919 | ||
920 | if(NS_FAILED(nsres)) | |
921 | ERR("AddRequest failed:%08x\n", nsres); | |
922 | } | |
923 | ||
924 | #define NSCHANNELBSC_THIS(bsc) ((nsChannelBSC*) bsc) | |
925 | ||
926 | static void nsChannelBSC_destroy(BSCallback *bsc) | |
927 | { | |
928 | nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); | |
929 | ||
930 | if(This->nschannel) | |
931 | nsIChannel_Release(NSCHANNEL(This->nschannel)); | |
932 | if(This->nslistener) | |
933 | nsIStreamListener_Release(This->nslistener); | |
934 | if(This->nscontext) | |
935 | nsISupports_Release(This->nscontext); | |
936 | if(This->nsstream) | |
937 | nsIInputStream_Release(NSINSTREAM(This->nsstream)); | |
938 | heap_free(This); | |
939 | } | |
940 | ||
941 | static HRESULT nsChannelBSC_start_binding(BSCallback *bsc) | |
942 | { | |
943 | nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); | |
944 | ||
945 | add_nsrequest(This); | |
946 | ||
947 | return S_OK; | |
948 | } | |
949 | ||
950 | static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result) | |
951 | { | |
952 | nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); | |
953 | ||
954 | on_stop_nsrequest(This); | |
955 | ||
956 | if(This->nslistener) { | |
957 | if(This->nschannel->load_group) { | |
958 | nsresult nsres; | |
959 | ||
960 | nsres = nsILoadGroup_RemoveRequest(This->nschannel->load_group, | |
961 | (nsIRequest*)NSCHANNEL(This->nschannel), NULL, NS_OK); | |
962 | if(NS_FAILED(nsres)) | |
963 | ERR("RemoveRequest failed: %08x\n", nsres); | |
964 | } | |
965 | } | |
966 | ||
967 | if(FAILED(result)) | |
968 | return S_OK; | |
969 | ||
970 | if(This->bsc.doc && This->bsc.doc->bscallback == This && !This->bsc.doc->nscontainer) { | |
971 | task_t *task = heap_alloc(sizeof(task_t)); | |
972 | ||
973 | task->doc = This->bsc.doc; | |
974 | task->task_id = TASK_PARSECOMPLETE; | |
975 | task->next = NULL; | |
976 | ||
977 | /* | |
978 | * This should be done in the worker thread that parses HTML, | |
979 | * but we don't have such thread. | |
980 | */ | |
981 | push_task(task); | |
982 | } | |
983 | ||
984 | return S_OK; | |
985 | } | |
986 | ||
987 | static HRESULT nsChannelBSC_read_data(BSCallback *bsc, IStream *stream) | |
988 | { | |
989 | nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); | |
990 | ||
991 | return read_stream_data(This, stream); | |
992 | } | |
993 | ||
994 | static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR status_text) | |
995 | { | |
996 | nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); | |
997 | ||
998 | switch(status_code) { | |
8abf7a8c | 999 | case BINDSTATUS_MIMETYPEAVAILABLE: |
c8bb048b JC |
1000 | if(!This->nschannel) |
1001 | return S_OK; | |
c8bb048b | 1002 | |
8abf7a8c JC |
1003 | heap_free(This->nschannel->content_type); |
1004 | This->nschannel->content_type = heap_strdupWtoA(status_text); | |
c8bb048b JC |
1005 | } |
1006 | ||
1007 | return S_OK; | |
1008 | } | |
1009 | ||
1010 | #undef NSCHANNELBSC_THIS | |
1011 | ||
1012 | static const BSCallbackVtbl nsChannelBSCVtbl = { | |
1013 | nsChannelBSC_destroy, | |
1014 | nsChannelBSC_start_binding, | |
1015 | nsChannelBSC_stop_binding, | |
1016 | nsChannelBSC_read_data, | |
1017 | nsChannelBSC_on_progress, | |
1018 | }; | |
1019 | ||
1020 | nsChannelBSC *create_channelbsc(IMoniker *mon) | |
1021 | { | |
1022 | nsChannelBSC *ret = heap_alloc_zero(sizeof(*ret)); | |
1023 | ||
1024 | init_bscallback(&ret->bsc, &nsChannelBSCVtbl, mon, BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA); | |
1025 | ||
1026 | return ret; | |
1027 | } | |
1028 | ||
1029 | IMoniker *get_channelbsc_mon(nsChannelBSC *This) | |
979b42d7 | 1030 | { |
c8bb048b JC |
1031 | if(This->bsc.mon) |
1032 | IMoniker_AddRef(This->bsc.mon); | |
1033 | return This->bsc.mon; | |
979b42d7 JC |
1034 | } |
1035 | ||
c8bb048b | 1036 | void set_document_bscallback(HTMLDocument *doc, nsChannelBSC *callback) |
ccd33999 | 1037 | { |
f309cdf7 JC |
1038 | BSCallback *iter; |
1039 | ||
ccd33999 | 1040 | if(doc->bscallback) { |
c8bb048b JC |
1041 | if(doc->bscallback->bsc.binding) |
1042 | IBinding_Abort(doc->bscallback->bsc.binding); | |
1043 | doc->bscallback->bsc.doc = NULL; | |
1044 | IBindStatusCallback_Release(STATUSCLB(&doc->bscallback->bsc)); | |
ccd33999 JC |
1045 | } |
1046 | ||
f309cdf7 JC |
1047 | LIST_FOR_EACH_ENTRY(iter, &doc->bindings, BSCallback, entry) { |
1048 | iter->doc = NULL; | |
1049 | list_remove(&iter->entry); | |
1050 | } | |
1051 | ||
ccd33999 JC |
1052 | doc->bscallback = callback; |
1053 | ||
1054 | if(callback) { | |
c8bb048b JC |
1055 | IBindStatusCallback_AddRef(STATUSCLB(&callback->bsc)); |
1056 | callback->bsc.doc = doc; | |
ccd33999 JC |
1057 | } |
1058 | } | |
920f628c | 1059 | |
c8bb048b | 1060 | HRESULT channelbsc_load_stream(nsChannelBSC *bscallback, IStream *stream) |
920f628c JC |
1061 | { |
1062 | HRESULT hres; | |
1063 | ||
1064 | const char text_html[] = "text/html"; | |
1065 | ||
1066 | add_nsrequest(bscallback); | |
1067 | ||
8abf7a8c JC |
1068 | if(bscallback->nschannel) |
1069 | bscallback->nschannel->content_type = heap_strdupA(text_html); | |
920f628c JC |
1070 | |
1071 | hres = read_stream_data(bscallback, stream); | |
c8bb048b | 1072 | IBindStatusCallback_OnStopBinding(STATUSCLB(&bscallback->bsc), hres, ERROR_SUCCESS); |
920f628c JC |
1073 | |
1074 | return hres; | |
1075 | } | |
f792ada4 | 1076 | |
c8bb048b | 1077 | void channelbsc_set_channel(nsChannelBSC *This, nsChannel *channel, nsIStreamListener *listener, nsISupports *context) |
f792ada4 JC |
1078 | { |
1079 | nsIChannel_AddRef(NSCHANNEL(channel)); | |
1080 | This->nschannel = channel; | |
1081 | ||
1082 | nsIStreamListener_AddRef(listener); | |
1083 | This->nslistener = listener; | |
1084 | ||
1085 | if(context) { | |
1086 | nsISupports_AddRef(context); | |
1087 | This->nscontext = context; | |
1088 | } | |
1089 | } | |
6738db5a JC |
1090 | |
1091 | void hlink_frame_navigate(HTMLDocument *doc, IHlinkFrame *hlink_frame, | |
1092 | LPCWSTR uri, nsIInputStream *post_data_stream, DWORD hlnf) | |
1093 | { | |
1094 | BSCallback *callback; | |
1095 | IBindCtx *bindctx; | |
1096 | IMoniker *mon; | |
1097 | IHlink *hlink; | |
1098 | HRESULT hr; | |
1099 | ||
c8bb048b | 1100 | callback = &create_channelbsc(NULL)->bsc; |
6738db5a JC |
1101 | |
1102 | if(post_data_stream) { | |
1103 | parse_post_data(post_data_stream, &callback->headers, &callback->post_data, | |
1104 | &callback->post_data_len); | |
1105 | TRACE("headers = %s post_data = %s\n", debugstr_w(callback->headers), | |
1106 | debugstr_an(callback->post_data, callback->post_data_len)); | |
1107 | } | |
1108 | ||
1109 | hr = CreateAsyncBindCtx(0, STATUSCLB(callback), NULL, &bindctx); | |
1110 | if (FAILED(hr)) { | |
1111 | IBindStatusCallback_Release(STATUSCLB(callback)); | |
1112 | return; | |
1113 | } | |
1114 | ||
1115 | hr = CoCreateInstance(&CLSID_StdHlink, NULL, CLSCTX_INPROC_SERVER, &IID_IHlink, (LPVOID*)&hlink); | |
1116 | if (FAILED(hr)) { | |
1117 | IBindCtx_Release(bindctx); | |
1118 | IBindStatusCallback_Release(STATUSCLB(callback)); | |
1119 | return; | |
1120 | } | |
1121 | ||
1122 | hr = CreateURLMoniker(NULL, uri, &mon); | |
1123 | if (SUCCEEDED(hr)) { | |
1124 | IHlink_SetMonikerReference(hlink, 0, mon, NULL); | |
1125 | ||
1126 | if(hlnf & HLNF_OPENINNEWWINDOW) { | |
1127 | static const WCHAR wszBlank[] = {'_','b','l','a','n','k',0}; | |
1128 | IHlink_SetTargetFrameName(hlink, wszBlank); /* FIXME */ | |
1129 | } | |
1130 | ||
1131 | IHlinkFrame_Navigate(hlink_frame, hlnf, bindctx, STATUSCLB(callback), hlink); | |
1132 | ||
1133 | IMoniker_Release(mon); | |
1134 | } | |
1135 | ||
1136 | IBindCtx_Release(bindctx); | |
1137 | IBindStatusCallback_Release(STATUSCLB(callback)); | |
1138 | } |