2 * Copyright 2006 Jacek Caban for CodeWeavers
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.
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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
36 #include "mshtml_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
40 #define CONTENT_LENGTH "Content-Length"
42 #define STATUSCLB_THIS(iface) DEFINE_THIS(BSCallback, BindStatusCallback, iface)
45 const IBindStatusCallbackVtbl
*lpBindStatusCallbackVtbl
;
46 const IServiceProviderVtbl
*lpServiceProviderVtbl
;
47 const IHttpNegotiate2Vtbl
*lpHttpNegotiate2Vtbl
;
48 const IInternetBindInfoVtbl
*lpInternetBindInfoVtbl
;
57 #define HTTPNEG(x) ((IHttpNegotiate2*) &(x)->lpHttpNegotiate2Vtbl)
58 #define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl);
60 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
61 REFIID riid
, void **ppv
)
63 BSCallback
*This
= STATUSCLB_THIS(iface
);
66 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
67 TRACE("(%p)->(IID_IUnknown, %p)\n", This
, ppv
);
68 *ppv
= STATUSCLB(This
);
69 }else if(IsEqualGUID(&IID_IBindStatusCallback
, riid
)) {
70 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This
, ppv
);
71 *ppv
= STATUSCLB(This
);
72 }else if(IsEqualGUID(&IID_IServiceProvider
, riid
)) {
73 TRACE("(%p)->(IID_IServiceProvider %p)\n", This
, ppv
);
74 *ppv
= SERVPROV(This
);
75 }else if(IsEqualGUID(&IID_IHttpNegotiate
, riid
)) {
76 TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This
, ppv
);
78 }else if(IsEqualGUID(&IID_IHttpNegotiate2
, riid
)) {
79 TRACE("(%p)->(IID_IHttpNegotiate2 %p)\n", This
, ppv
);
81 }else if(IsEqualGUID(&IID_IInternetBindInfo
, riid
)) {
82 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This
, ppv
);
83 *ppv
= BINDINFO(This
);
87 IBindStatusCallback_AddRef(STATUSCLB(This
));
91 TRACE("Unsupported riid = %s\n", debugstr_guid(riid
));
95 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
97 BSCallback
*This
= STATUSCLB_THIS(iface
);
98 LONG ref
= InterlockedIncrement(&This
->ref
);
100 TRACE("(%p) ref = %ld\n", This
, ref
);
105 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
107 BSCallback
*This
= STATUSCLB_THIS(iface
);
108 LONG ref
= InterlockedDecrement(&This
->ref
);
110 TRACE("(%p) ref = %ld\n", This
, ref
);
114 GlobalFree(This
->post_data
);
115 HeapFree(GetProcessHeap(), 0, This
->headers
);
116 HeapFree(GetProcessHeap(), 0, This
);
122 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
123 DWORD dwReserved
, IBinding
*pbind
)
125 BSCallback
*This
= STATUSCLB_THIS(iface
);
126 FIXME("(%p)->(%ld %p)\n", This
, dwReserved
, pbind
);
130 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pnPriority
)
132 BSCallback
*This
= STATUSCLB_THIS(iface
);
133 FIXME("(%p)->(%p)\n", This
, pnPriority
);
137 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
139 BSCallback
*This
= STATUSCLB_THIS(iface
);
140 FIXME("(%p)->(%ld)\n", This
, reserved
);
144 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
145 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
147 BSCallback
*This
= STATUSCLB_THIS(iface
);
148 TRACE("%p)->(%lu %lu %lu %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
,
149 debugstr_w(szStatusText
));
153 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
,
154 HRESULT hresult
, LPCWSTR szError
)
156 BSCallback
*This
= STATUSCLB_THIS(iface
);
157 FIXME("(%p)->(%08lx %s)\n", This
, hresult
, debugstr_w(szError
));
161 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
162 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
164 BSCallback
*This
= STATUSCLB_THIS(iface
);
167 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
169 *grfBINDF
= BINDF_ASYNCHRONOUS
| BINDF_ASYNCSTORAGE
| BINDF_PULLDATA
;
171 size
= pbindinfo
->cbSize
;
172 memset(pbindinfo
, 0, size
);
173 pbindinfo
->cbSize
= size
;
175 pbindinfo
->cbStgmedData
= This
->post_data_len
;
176 pbindinfo
->dwCodePage
= CP_UTF8
;
177 pbindinfo
->dwOptions
= 0x00020000;
179 if(This
->post_data
) {
180 pbindinfo
->dwBindVerb
= BINDVERB_POST
;
182 pbindinfo
->stgmedData
.tymed
= TYMED_HGLOBAL
;
183 pbindinfo
->stgmedData
.u
.hGlobal
= This
->post_data
;
184 pbindinfo
->stgmedData
.pUnkForRelease
= (IUnknown
*)STATUSCLB(This
);
185 IBindStatusCallback_AddRef(STATUSCLB(This
));
191 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
,
192 DWORD grfBSCF
, DWORD dwSize
, FORMATETC
*pformatetc
, STGMEDIUM
*pstgmed
)
194 BSCallback
*This
= STATUSCLB_THIS(iface
);
195 FIXME("(%p)->(%08lx %ld %p %p)\n", This
, grfBSCF
, dwSize
, pformatetc
, pstgmed
);
199 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
200 REFIID riid
, IUnknown
*punk
)
202 BSCallback
*This
= STATUSCLB_THIS(iface
);
203 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), punk
);
207 #undef STATUSCLB_THIS
209 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
210 BindStatusCallback_QueryInterface
,
211 BindStatusCallback_AddRef
,
212 BindStatusCallback_Release
,
213 BindStatusCallback_OnStartBinding
,
214 BindStatusCallback_GetPriority
,
215 BindStatusCallback_OnLowResource
,
216 BindStatusCallback_OnProgress
,
217 BindStatusCallback_OnStopBinding
,
218 BindStatusCallback_GetBindInfo
,
219 BindStatusCallback_OnDataAvailable
,
220 BindStatusCallback_OnObjectAvailable
223 #define HTTPNEG_THIS(iface) DEFINE_THIS(BSCallback, HttpNegotiate2, iface)
225 static HRESULT WINAPI
HttpNegotiate_QueryInterface(IHttpNegotiate2
*iface
,
226 REFIID riid
, void **ppv
)
228 BSCallback
*This
= HTTPNEG_THIS(iface
);
229 return IBindStatusCallback_QueryInterface(STATUSCLB(This
), riid
, ppv
);
232 static ULONG WINAPI
HttpNegotiate_AddRef(IHttpNegotiate2
*iface
)
234 BSCallback
*This
= HTTPNEG_THIS(iface
);
235 return IBindStatusCallback_AddRef(STATUSCLB(This
));
238 static ULONG WINAPI
HttpNegotiate_Release(IHttpNegotiate2
*iface
)
240 BSCallback
*This
= HTTPNEG_THIS(iface
);
241 return IBindStatusCallback_Release(STATUSCLB(This
));
244 static HRESULT WINAPI
HttpNegotiate_BeginningTransaction(IHttpNegotiate2
*iface
,
245 LPCWSTR szURL
, LPCWSTR szHeaders
, DWORD dwReserved
, LPWSTR
*pszAdditionalHeaders
)
247 BSCallback
*This
= HTTPNEG_THIS(iface
);
250 TRACE("(%p)->(%s %s %ld %p)\n", This
, debugstr_w(szURL
), debugstr_w(szHeaders
),
251 dwReserved
, pszAdditionalHeaders
);
254 *pszAdditionalHeaders
= NULL
;
258 size
= (strlenW(This
->headers
)+1)*sizeof(WCHAR
);
259 *pszAdditionalHeaders
= CoTaskMemAlloc(size
);
260 memcpy(*pszAdditionalHeaders
, This
->headers
, size
);
265 static HRESULT WINAPI
HttpNegotiate_OnResponse(IHttpNegotiate2
*iface
, DWORD dwResponseCode
,
266 LPCWSTR szResponseHeaders
, LPCWSTR szRequestHeaders
, LPWSTR
*pszAdditionalRequestHeaders
)
268 BSCallback
*This
= HTTPNEG_THIS(iface
);
269 FIXME("(%p)->(%ld %s %s %p)\n", This
, dwResponseCode
, debugstr_w(szResponseHeaders
),
270 debugstr_w(szRequestHeaders
), pszAdditionalRequestHeaders
);
274 static HRESULT WINAPI
HttpNegotiate_GetRootSecurityId(IHttpNegotiate2
*iface
,
275 BYTE
*pbSecurityId
, DWORD
*pcbSecurityId
, DWORD_PTR dwReserved
)
277 BSCallback
*This
= HTTPNEG_THIS(iface
);
278 FIXME("(%p)->(%p %p %ld)\n", This
, pbSecurityId
, pcbSecurityId
, dwReserved
);
284 static const IHttpNegotiate2Vtbl HttpNegotiate2Vtbl
= {
285 HttpNegotiate_QueryInterface
,
286 HttpNegotiate_AddRef
,
287 HttpNegotiate_Release
,
288 HttpNegotiate_BeginningTransaction
,
289 HttpNegotiate_OnResponse
,
290 HttpNegotiate_GetRootSecurityId
293 #define BINDINFO_THIS(iface) DEFINE_THIS(BSCallback, InternetBindInfo, iface)
295 static HRESULT WINAPI
InternetBindInfo_QueryInterface(IInternetBindInfo
*iface
,
296 REFIID riid
, void **ppv
)
298 BSCallback
*This
= BINDINFO_THIS(iface
);
299 return IBindStatusCallback_QueryInterface(STATUSCLB(This
), riid
, ppv
);
302 static ULONG WINAPI
InternetBindInfo_AddRef(IInternetBindInfo
*iface
)
304 BSCallback
*This
= BINDINFO_THIS(iface
);
305 return IBindStatusCallback_AddRef(STATUSCLB(This
));
308 static ULONG WINAPI
InternetBindInfo_Release(IInternetBindInfo
*iface
)
310 BSCallback
*This
= BINDINFO_THIS(iface
);
311 return IBindStatusCallback_Release(STATUSCLB(This
));
314 static HRESULT WINAPI
InternetBindInfo_GetBindInfo(IInternetBindInfo
*iface
,
315 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
317 BSCallback
*This
= BINDINFO_THIS(iface
);
318 FIXME("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
322 static HRESULT WINAPI
InternetBindInfo_GetBindString(IInternetBindInfo
*iface
,
323 ULONG ulStringType
, LPOLESTR
*ppwzStr
, ULONG cEl
, ULONG
*pcElFetched
)
325 BSCallback
*This
= BINDINFO_THIS(iface
);
326 FIXME("(%p)->(%lu %p %lu %p)\n", This
, ulStringType
, ppwzStr
, cEl
, pcElFetched
);
332 static const IInternetBindInfoVtbl InternetBindInfoVtbl
= {
333 InternetBindInfo_QueryInterface
,
334 InternetBindInfo_AddRef
,
335 InternetBindInfo_Release
,
336 InternetBindInfo_GetBindInfo
,
337 InternetBindInfo_GetBindString
340 #define SERVPROV_THIS(iface) DEFINE_THIS(BSCallback, ServiceProvider, iface)
342 static HRESULT WINAPI
BSCServiceProvider_QueryInterface(IServiceProvider
*iface
,
343 REFIID riid
, void **ppv
)
345 BSCallback
*This
= SERVPROV_THIS(iface
);
346 return IBindStatusCallback_QueryInterface(STATUSCLB(This
), riid
, ppv
);
349 static ULONG WINAPI
BSCServiceProvider_AddRef(IServiceProvider
*iface
)
351 BSCallback
*This
= SERVPROV_THIS(iface
);
352 return IBindStatusCallback_AddRef(STATUSCLB(This
));
355 static ULONG WINAPI
BSCServiceProvider_Release(IServiceProvider
*iface
)
357 BSCallback
*This
= SERVPROV_THIS(iface
);
358 return IBindStatusCallback_Release(STATUSCLB(This
));
361 static HRESULT WINAPI
BSCServiceProvider_QueryService(IServiceProvider
*iface
,
362 REFGUID guidService
, REFIID riid
, void **ppv
)
364 BSCallback
*This
= SERVPROV_THIS(iface
);
365 FIXME("(%p)->(%s %s %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
371 static const IServiceProviderVtbl ServiceProviderVtbl
= {
372 BSCServiceProvider_QueryInterface
,
373 BSCServiceProvider_AddRef
,
374 BSCServiceProvider_Release
,
375 BSCServiceProvider_QueryService
378 static IBindStatusCallback
*BSCallback_Create(HTMLDocument
*doc
, LPCOLESTR url
,
379 HGLOBAL post_data
, ULONG post_data_len
, LPWSTR headers
)
381 BSCallback
*ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(BSCallback
));
383 ret
->lpBindStatusCallbackVtbl
= &BindStatusCallbackVtbl
;
384 ret
->lpServiceProviderVtbl
= &ServiceProviderVtbl
;
385 ret
->lpHttpNegotiate2Vtbl
= &HttpNegotiate2Vtbl
;
386 ret
->lpInternetBindInfoVtbl
= &InternetBindInfoVtbl
;
388 ret
->post_data
= post_data
;
389 ret
->headers
= headers
;
390 ret
->post_data_len
= post_data_len
;
392 return STATUSCLB(ret
);
395 static void parse_post_data(nsIInputStream
*post_data_stream
, LPWSTR
*headers_ret
,
396 HGLOBAL
*post_data_ret
, ULONG
*post_data_len_ret
)
398 PRUint32 post_data_len
= 0, available
= 0;
399 HGLOBAL post_data
= NULL
;
400 LPWSTR headers
= NULL
;
401 DWORD headers_len
= 0, len
;
402 const char *ptr
, *ptr2
, *post_data_end
;
404 nsIInputStream_Available(post_data_stream
, &available
);
405 post_data
= GlobalAlloc(0, available
+1);
406 nsIInputStream_Read(post_data_stream
, post_data
, available
, &post_data_len
);
408 TRACE("post_data = %s\n", debugstr_an(post_data
, post_data_len
));
410 ptr
= ptr2
= post_data
;
411 post_data_end
= (const char*)post_data
+post_data_len
;
413 while(ptr
< post_data_end
&& (*ptr
!= '\r' || ptr
[1] != '\n')) {
414 while(ptr
< post_data_end
&& (*ptr
!= '\r' || ptr
[1] != '\n'))
424 if(ptr
-ptr2
>= sizeof(CONTENT_LENGTH
)
425 && CompareStringA(LOCALE_SYSTEM_DEFAULT
, NORM_IGNORECASE
,
426 CONTENT_LENGTH
, sizeof(CONTENT_LENGTH
)-1,
427 ptr2
, sizeof(CONTENT_LENGTH
)-1) == CSTR_EQUAL
) {
432 len
= MultiByteToWideChar(CP_ACP
, 0, ptr2
, ptr
-ptr2
, NULL
, 0);
435 headers
= HeapReAlloc(GetProcessHeap(), 0, headers
,
436 (headers_len
+len
+1)*sizeof(WCHAR
));
438 headers
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
440 len
= MultiByteToWideChar(CP_ACP
, 0, ptr2
, ptr
-ptr2
, headers
+headers_len
, -1);
446 headers
[headers_len
] = 0;
447 *headers_ret
= headers
;
449 if(ptr
>= post_data_end
-2) {
450 GlobalFree(post_data
);
457 post_data_len
-= ptr
-(const char*)post_data
;
458 memmove(post_data
, ptr
, post_data_len
);
459 post_data
= GlobalReAlloc(post_data
, post_data_len
+1, 0);
462 *post_data_ret
= post_data
;
463 *post_data_len_ret
= post_data_len
;
466 void hlink_frame_navigate(HTMLDocument
*doc
, IHlinkFrame
*hlink_frame
,
467 LPCWSTR uri
, nsIInputStream
*post_data_stream
, DWORD hlnf
)
469 IBindStatusCallback
*callback
;
473 PRUint32 post_data_len
= 0;
474 HGLOBAL post_data
= NULL
;
475 LPWSTR headers
= NULL
;
477 if(post_data_stream
) {
478 parse_post_data(post_data_stream
, &headers
, &post_data
, &post_data_len
);
479 TRACE("headers = %s post_data = %s\n", debugstr_w(headers
),
480 debugstr_an(post_data
, post_data_len
));
483 callback
= BSCallback_Create(doc
, uri
, post_data
, post_data_len
, headers
);
484 CreateAsyncBindCtx(0, callback
, NULL
, &bindctx
);
486 hlink
= Hlink_Create();
488 CreateURLMoniker(NULL
, uri
, &mon
);
489 IHlink_SetMonikerReference(hlink
, 0, mon
, NULL
);
491 if(hlnf
& HLNF_OPENINNEWWINDOW
) {
492 static const WCHAR wszBlank
[] = {'_','b','l','a','n','k',0};
493 IHlink_SetTargetFrameName(hlink
, wszBlank
); /* FIXME */
496 IHlinkFrame_Navigate(hlink_frame
, hlnf
, bindctx
, callback
, hlink
);
498 IBindCtx_Release(bindctx
);
499 IBindStatusCallback_Release(callback
);
500 IMoniker_Release(mon
);