2759f3d226b39b20e8a80231b9e42cc9fcb11d15
[reactos.git] / dll / win32 / urlmon / bindctx.c
1 /*
2 * Copyright 2007 Jacek Caban for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include <stdio.h>
20
21 #include "urlmon_main.h"
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
25
26 static WCHAR bscb_holderW[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
27
28 extern IID IID_IBindStatusCallbackHolder;
29
30 typedef struct {
31 IBindStatusCallbackEx IBindStatusCallbackEx_iface;
32 IInternetBindInfo IInternetBindInfo_iface;
33 IServiceProvider IServiceProvider_iface;
34 IHttpNegotiate2 IHttpNegotiate2_iface;
35 IAuthenticate IAuthenticate_iface;
36
37 LONG ref;
38
39 IBindStatusCallback *callback;
40 IServiceProvider *serv_prov;
41 } BindStatusCallback;
42
43 static void *get_callback_iface(BindStatusCallback *This, REFIID riid)
44 {
45 void *ret;
46 HRESULT hres;
47
48 hres = IBindStatusCallback_QueryInterface(This->callback, riid, (void**)&ret);
49 if(FAILED(hres) && This->serv_prov)
50 hres = IServiceProvider_QueryService(This->serv_prov, riid, riid, &ret);
51
52 return SUCCEEDED(hres) ? ret : NULL;
53 }
54
55 static IBindStatusCallback *bsch_from_bctx(IBindCtx *bctx)
56 {
57 IBindStatusCallback *bsc;
58 IUnknown *unk;
59 HRESULT hres;
60
61 hres = IBindCtx_GetObjectParam(bctx, bscb_holderW, &unk);
62 if(FAILED(hres))
63 return NULL;
64
65 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc);
66 IUnknown_Release(unk);
67 return SUCCEEDED(hres) ? bsc : NULL;
68 }
69
70 IBindStatusCallback *bsc_from_bctx(IBindCtx *bctx)
71 {
72 BindStatusCallback *holder;
73 IBindStatusCallback *bsc;
74 HRESULT hres;
75
76 bsc = bsch_from_bctx(bctx);
77 if(!bsc)
78 return NULL;
79
80 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
81 if(FAILED(hres))
82 return bsc;
83
84 if(holder->callback) {
85 IBindStatusCallback_Release(bsc);
86 bsc = holder->callback;
87 IBindStatusCallback_AddRef(bsc);
88 }
89
90 IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface);
91 return bsc;
92 }
93
94 static inline BindStatusCallback *impl_from_IBindStatusCallbackEx(IBindStatusCallbackEx *iface)
95 {
96 return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallbackEx_iface);
97 }
98
99 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallbackEx *iface,
100 REFIID riid, void **ppv)
101 {
102 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
103
104 *ppv = NULL;
105
106 if(IsEqualGUID(&IID_IUnknown, riid)) {
107 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
108 *ppv = &This->IBindStatusCallbackEx_iface;
109 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
110 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
111 *ppv = &This->IBindStatusCallbackEx_iface;
112 }else if(IsEqualGUID(&IID_IBindStatusCallbackEx, riid)) {
113 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
114 *ppv = &This->IBindStatusCallbackEx_iface;
115 }else if(IsEqualGUID(&IID_IBindStatusCallbackHolder, riid)) {
116 TRACE("(%p)->(IID_IBindStatusCallbackHolder, %p)\n", This, ppv);
117 *ppv = This;
118 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
119 TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
120 *ppv = &This->IServiceProvider_iface;
121 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
122 TRACE("(%p)->(IID_IHttpNegotiate, %p)\n", This, ppv);
123 *ppv = &This->IHttpNegotiate2_iface;
124 }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
125 TRACE("(%p)->(IID_IHttpNegotiate2, %p)\n", This, ppv);
126 *ppv = &This->IHttpNegotiate2_iface;
127 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
128 TRACE("(%p)->(IID_IAuthenticate, %p)\n", This, ppv);
129 *ppv = &This->IAuthenticate_iface;
130 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
131 TRACE("(%p)->(IID_IInternetBindInfo, %p)\n", This, ppv);
132 *ppv = &This->IInternetBindInfo_iface;
133 }
134
135 if(*ppv) {
136 IUnknown_AddRef((IUnknown*)*ppv);
137 return S_OK;
138 }
139
140 TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
141 return E_NOINTERFACE;
142 }
143
144 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallbackEx *iface)
145 {
146 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
147 LONG ref = InterlockedIncrement(&This->ref);
148
149 TRACE("(%p) ref = %d\n", This, ref);
150
151 return ref;
152 }
153
154 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallbackEx *iface)
155 {
156 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
157 LONG ref = InterlockedDecrement(&This->ref);
158
159 TRACE("(%p) ref = %d\n", This, ref);
160
161 if(!ref) {
162 if(This->serv_prov)
163 IServiceProvider_Release(This->serv_prov);
164 IBindStatusCallback_Release(This->callback);
165 heap_free(This);
166 }
167
168 return ref;
169 }
170
171 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallbackEx *iface,
172 DWORD dwReserved, IBinding *pbind)
173 {
174 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
175
176 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
177
178 return IBindStatusCallback_OnStartBinding(This->callback, 0xff, pbind);
179 }
180
181 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallbackEx *iface, LONG *pnPriority)
182 {
183 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
184
185 TRACE("(%p)->(%p)\n", This, pnPriority);
186
187 return IBindStatusCallback_GetPriority(This->callback, pnPriority);
188 }
189
190 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallbackEx *iface, DWORD reserved)
191 {
192 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
193
194 TRACE("(%p)->(%d)\n", This, reserved);
195
196 return IBindStatusCallback_OnLowResource(This->callback, reserved);
197 }
198
199 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallbackEx *iface, ULONG ulProgress,
200 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
201 {
202 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
203
204 TRACE("%p)->(%u %u %s %s)\n", This, ulProgress, ulProgressMax, debugstr_bindstatus(ulStatusCode),
205 debugstr_w(szStatusText));
206
207 return IBindStatusCallback_OnProgress(This->callback, ulProgress,
208 ulProgressMax, ulStatusCode, szStatusText);
209 }
210
211 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallbackEx *iface,
212 HRESULT hresult, LPCWSTR szError)
213 {
214 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
215
216 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
217
218 return IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
219 }
220
221 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallbackEx *iface,
222 DWORD *grfBINDF, BINDINFO *pbindinfo)
223 {
224 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
225 IBindStatusCallbackEx *bscex;
226 HRESULT hres;
227
228 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
229
230 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex);
231 if(SUCCEEDED(hres)) {
232 DWORD bindf2 = 0, reserv = 0;
233
234 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, &bindf2, &reserv);
235 IBindStatusCallbackEx_Release(bscex);
236 }else {
237 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
238 }
239
240 return hres;
241 }
242
243 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallbackEx *iface,
244 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
245 {
246 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
247
248 TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
249
250 return IBindStatusCallback_OnDataAvailable(This->callback, grfBSCF, dwSize, pformatetc, pstgmed);
251 }
252
253 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallbackEx *iface,
254 REFIID riid, IUnknown *punk)
255 {
256 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
257
258 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
259
260 return IBindStatusCallback_OnObjectAvailable(This->callback, riid, punk);
261 }
262
263 static HRESULT WINAPI BindStatusCallback_GetBindInfoEx(IBindStatusCallbackEx *iface, DWORD *grfBINDF,
264 BINDINFO *pbindinfo, DWORD *grfBINDF2, DWORD *pdwReserved)
265 {
266 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
267 IBindStatusCallbackEx *bscex;
268 HRESULT hres;
269
270 TRACE("(%p)->(%p %p %p %p)\n", This, grfBINDF, pbindinfo, grfBINDF2, pdwReserved);
271
272 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex);
273 if(SUCCEEDED(hres)) {
274 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, grfBINDF2, pdwReserved);
275 IBindStatusCallbackEx_Release(bscex);
276 }else {
277 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
278 }
279
280 return hres;
281 }
282
283 static const IBindStatusCallbackExVtbl BindStatusCallbackExVtbl = {
284 BindStatusCallback_QueryInterface,
285 BindStatusCallback_AddRef,
286 BindStatusCallback_Release,
287 BindStatusCallback_OnStartBinding,
288 BindStatusCallback_GetPriority,
289 BindStatusCallback_OnLowResource,
290 BindStatusCallback_OnProgress,
291 BindStatusCallback_OnStopBinding,
292 BindStatusCallback_GetBindInfo,
293 BindStatusCallback_OnDataAvailable,
294 BindStatusCallback_OnObjectAvailable,
295 BindStatusCallback_GetBindInfoEx
296 };
297
298 static inline BindStatusCallback *impl_from_IServiceProvider(IServiceProvider *iface)
299 {
300 return CONTAINING_RECORD(iface, BindStatusCallback, IServiceProvider_iface);
301 }
302
303 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
304 REFIID riid, void **ppv)
305 {
306 BindStatusCallback *This = impl_from_IServiceProvider(iface);
307 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
308 }
309
310 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
311 {
312 BindStatusCallback *This = impl_from_IServiceProvider(iface);
313 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
314 }
315
316 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
317 {
318 BindStatusCallback *This = impl_from_IServiceProvider(iface);
319 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
320 }
321
322 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
323 REFGUID guidService, REFIID riid, void **ppv)
324 {
325 BindStatusCallback *This = impl_from_IServiceProvider(iface);
326 HRESULT hres;
327
328 if(IsEqualGUID(&IID_IHttpNegotiate, guidService)) {
329 TRACE("(%p)->(IID_IHttpNegotiate %s %p)\n", This, debugstr_guid(riid), ppv);
330 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
331 }
332
333 if(IsEqualGUID(&IID_IHttpNegotiate2, guidService)) {
334 TRACE("(%p)->(IID_IHttpNegotiate2 %s %p)\n", This, debugstr_guid(riid), ppv);
335 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
336 }
337
338 if(IsEqualGUID(&IID_IAuthenticate, guidService)) {
339 TRACE("(%p)->(IID_IAuthenticate %s %p)\n", This, debugstr_guid(riid), ppv);
340 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
341 }
342
343 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
344
345 hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv);
346 if(SUCCEEDED(hres))
347 return S_OK;
348
349 if(This->serv_prov) {
350 hres = IServiceProvider_QueryService(This->serv_prov, guidService, riid, ppv);
351 if(SUCCEEDED(hres))
352 return S_OK;
353 }
354
355 return E_NOINTERFACE;
356 }
357
358 static const IServiceProviderVtbl BSCServiceProviderVtbl = {
359 BSCServiceProvider_QueryInterface,
360 BSCServiceProvider_AddRef,
361 BSCServiceProvider_Release,
362 BSCServiceProvider_QueryService
363 };
364
365 static inline BindStatusCallback *impl_from_IHttpNegotiate2(IHttpNegotiate2 *iface)
366 {
367 return CONTAINING_RECORD(iface, BindStatusCallback, IHttpNegotiate2_iface);
368 }
369
370 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
371 REFIID riid, void **ppv)
372 {
373 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
374 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
375 }
376
377 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate2 *iface)
378 {
379 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
380 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
381 }
382
383 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate2 *iface)
384 {
385 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
386 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
387 }
388
389 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
390 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
391 {
392 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
393 IHttpNegotiate *http_negotiate;
394 HRESULT hres = S_OK;
395
396 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved,
397 pszAdditionalHeaders);
398
399 *pszAdditionalHeaders = NULL;
400
401 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
402 if(http_negotiate) {
403 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, szURL, szHeaders,
404 dwReserved, pszAdditionalHeaders);
405 IHttpNegotiate_Release(http_negotiate);
406 }
407
408 return hres;
409 }
410
411 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
412 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders,
413 LPWSTR *pszAdditionalRequestHeaders)
414 {
415 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
416 LPWSTR additional_headers = NULL;
417 IHttpNegotiate *http_negotiate;
418 HRESULT hres = S_OK;
419
420 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
421 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
422
423 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
424 if(http_negotiate) {
425 hres = IHttpNegotiate_OnResponse(http_negotiate, dwResponseCode, szResponseHeaders,
426 szRequestHeaders, &additional_headers);
427 IHttpNegotiate_Release(http_negotiate);
428 }
429
430 if(pszAdditionalRequestHeaders)
431 *pszAdditionalRequestHeaders = additional_headers;
432 else
433 CoTaskMemFree(additional_headers);
434
435 return hres;
436 }
437
438 static HRESULT WINAPI BSCHttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
439 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
440 {
441 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
442 IHttpNegotiate2 *http_negotiate2;
443 HRESULT hres = E_FAIL;
444
445 TRACE("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved);
446
447 http_negotiate2 = get_callback_iface(This, &IID_IHttpNegotiate2);
448 if(http_negotiate2) {
449 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, pbSecurityId,
450 pcbSecurityId, dwReserved);
451 IHttpNegotiate2_Release(http_negotiate2);
452 }
453
454 return hres;
455 }
456
457 static const IHttpNegotiate2Vtbl BSCHttpNegotiateVtbl = {
458 BSCHttpNegotiate_QueryInterface,
459 BSCHttpNegotiate_AddRef,
460 BSCHttpNegotiate_Release,
461 BSCHttpNegotiate_BeginningTransaction,
462 BSCHttpNegotiate_OnResponse,
463 BSCHttpNegotiate_GetRootSecurityId
464 };
465
466 static inline BindStatusCallback *impl_from_IAuthenticate(IAuthenticate *iface)
467 {
468 return CONTAINING_RECORD(iface, BindStatusCallback, IAuthenticate_iface);
469 }
470
471 static HRESULT WINAPI BSCAuthenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
472 {
473 BindStatusCallback *This = impl_from_IAuthenticate(iface);
474 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
475 }
476
477 static ULONG WINAPI BSCAuthenticate_AddRef(IAuthenticate *iface)
478 {
479 BindStatusCallback *This = impl_from_IAuthenticate(iface);
480 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
481 }
482
483 static ULONG WINAPI BSCAuthenticate_Release(IAuthenticate *iface)
484 {
485 BindStatusCallback *This = impl_from_IAuthenticate(iface);
486 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
487 }
488
489 static HRESULT WINAPI BSCAuthenticate_Authenticate(IAuthenticate *iface,
490 HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword)
491 {
492 BindStatusCallback *This = impl_from_IAuthenticate(iface);
493 FIXME("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword);
494 return E_NOTIMPL;
495 }
496
497 static const IAuthenticateVtbl BSCAuthenticateVtbl = {
498 BSCAuthenticate_QueryInterface,
499 BSCAuthenticate_AddRef,
500 BSCAuthenticate_Release,
501 BSCAuthenticate_Authenticate
502 };
503
504 static inline BindStatusCallback *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
505 {
506 return CONTAINING_RECORD(iface, BindStatusCallback, IInternetBindInfo_iface);
507 }
508
509 static HRESULT WINAPI BSCInternetBindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
510 {
511 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
512 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
513 }
514
515 static ULONG WINAPI BSCInternetBindInfo_AddRef(IInternetBindInfo *iface)
516 {
517 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
518 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
519 }
520
521 static ULONG WINAPI BSCInternetBindInfo_Release(IInternetBindInfo *iface)
522 {
523 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
524 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
525 }
526
527 static HRESULT WINAPI BSCInternetBindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *bindf, BINDINFO *bindinfo)
528 {
529 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
530 FIXME("(%p)->(%p %p)\n", This, bindf, bindinfo);
531 return E_NOTIMPL;
532 }
533
534 static HRESULT WINAPI BSCInternetBindInfo_GetBindString(IInternetBindInfo *iface, ULONG string_type,
535 WCHAR **strs, ULONG cnt, ULONG *fetched)
536 {
537 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
538 IInternetBindInfo *bind_info;
539 HRESULT hres;
540
541 TRACE("(%p)->(%d %p %d %p)\n", This, string_type, strs, cnt, fetched);
542
543 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IInternetBindInfo, (void**)&bind_info);
544 if(FAILED(hres))
545 return hres;
546
547 hres = IInternetBindInfo_GetBindString(bind_info, string_type, strs, cnt, fetched);
548
549 IInternetBindInfo_Release(bind_info);
550 return hres;
551 }
552
553 static IInternetBindInfoVtbl BSCInternetBindInfoVtbl = {
554 BSCInternetBindInfo_QueryInterface,
555 BSCInternetBindInfo_AddRef,
556 BSCInternetBindInfo_Release,
557 BSCInternetBindInfo_GetBindInfo,
558 BSCInternetBindInfo_GetBindString
559 };
560
561 static void set_callback(BindStatusCallback *This, IBindStatusCallback *bsc)
562 {
563 IServiceProvider *serv_prov;
564 HRESULT hres;
565
566 if(This->callback)
567 IBindStatusCallback_Release(This->callback);
568 if(This->serv_prov)
569 IServiceProvider_Release(This->serv_prov);
570
571 IBindStatusCallback_AddRef(bsc);
572 This->callback = bsc;
573
574 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&serv_prov);
575 This->serv_prov = hres == S_OK ? serv_prov : NULL;
576 }
577
578 HRESULT wrap_callback(IBindStatusCallback *bsc, IBindStatusCallback **ret_iface)
579 {
580 BindStatusCallback *ret;
581
582 ret = heap_alloc_zero(sizeof(BindStatusCallback));
583 if(!ret)
584 return E_OUTOFMEMORY;
585
586 ret->IBindStatusCallbackEx_iface.lpVtbl = &BindStatusCallbackExVtbl;
587 ret->IInternetBindInfo_iface.lpVtbl = &BSCInternetBindInfoVtbl;
588 ret->IServiceProvider_iface.lpVtbl = &BSCServiceProviderVtbl;
589 ret->IHttpNegotiate2_iface.lpVtbl = &BSCHttpNegotiateVtbl;
590 ret->IAuthenticate_iface.lpVtbl = &BSCAuthenticateVtbl;
591
592 ret->ref = 1;
593 set_callback(ret, bsc);
594
595 *ret_iface = (IBindStatusCallback*)&ret->IBindStatusCallbackEx_iface;
596 return S_OK;
597 }
598
599 /***********************************************************************
600 * RegisterBindStatusCallback (urlmon.@)
601 *
602 * Register a bind status callback.
603 *
604 * PARAMS
605 * pbc [I] Binding context
606 * pbsc [I] Callback to register
607 * ppbscPrevious [O] Destination for previous callback
608 * dwReserved [I] Reserved, must be 0.
609 *
610 * RETURNS
611 * Success: S_OK.
612 * Failure: E_INVALIDARG, if any argument is invalid, or
613 * E_OUTOFMEMORY if memory allocation fails.
614 */
615 HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc,
616 IBindStatusCallback **ppbscPrevious, DWORD dwReserved)
617 {
618 BindStatusCallback *holder;
619 IBindStatusCallback *bsc, *prev = NULL;
620 HRESULT hres;
621
622 TRACE("(%p %p %p %x)\n", pbc, pbsc, ppbscPrevious, dwReserved);
623
624 if (!pbc || !pbsc)
625 return E_INVALIDARG;
626
627 bsc = bsch_from_bctx(pbc);
628 if(bsc) {
629 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
630 if(SUCCEEDED(hres)) {
631 if(ppbscPrevious) {
632 IBindStatusCallback_AddRef(holder->callback);
633 *ppbscPrevious = holder->callback;
634 }
635
636 set_callback(holder, pbsc);
637
638 IBindStatusCallback_Release(bsc);
639 IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface);
640 return S_OK;
641 }else {
642 prev = bsc;
643 }
644
645 IBindCtx_RevokeObjectParam(pbc, bscb_holderW);
646 }
647
648 hres = wrap_callback(pbsc, &bsc);
649 if(SUCCEEDED(hres)) {
650 hres = IBindCtx_RegisterObjectParam(pbc, bscb_holderW, (IUnknown*)bsc);
651 IBindStatusCallback_Release(bsc);
652 }
653 if(FAILED(hres)) {
654 if(prev)
655 IBindStatusCallback_Release(prev);
656 return hres;
657 }
658
659 if(ppbscPrevious)
660 *ppbscPrevious = prev;
661 return S_OK;
662 }
663
664 /***********************************************************************
665 * RevokeBindStatusCallback (URLMON.@)
666 *
667 * Unregister a bind status callback.
668 *
669 * pbc [I] Binding context
670 * pbsc [I] Callback to unregister
671 *
672 * RETURNS
673 * Success: S_OK.
674 * Failure: E_INVALIDARG, if any argument is invalid
675 */
676 HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc)
677 {
678 IBindStatusCallback *callback;
679
680 TRACE("(%p %p)\n", pbc, pbsc);
681
682 if (!pbc || !pbsc)
683 return E_INVALIDARG;
684
685 callback = bsc_from_bctx(pbc);
686 if(!callback)
687 return S_OK;
688
689 if(callback == pbsc)
690 IBindCtx_RevokeObjectParam(pbc, bscb_holderW);
691
692 IBindStatusCallback_Release(callback);
693 return S_OK;
694 }
695
696 typedef struct {
697 IBindCtx IBindCtx_iface;
698
699 LONG ref;
700
701 IBindCtx *bindctx;
702 } AsyncBindCtx;
703
704 static inline AsyncBindCtx *impl_from_IBindCtx(IBindCtx *iface)
705 {
706 return CONTAINING_RECORD(iface, AsyncBindCtx, IBindCtx_iface);
707 }
708
709 static HRESULT WINAPI AsyncBindCtx_QueryInterface(IBindCtx *iface, REFIID riid, void **ppv)
710 {
711 AsyncBindCtx *This = impl_from_IBindCtx(iface);
712
713 *ppv = NULL;
714
715 if(IsEqualGUID(riid, &IID_IUnknown)) {
716 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
717 *ppv = &This->IBindCtx_iface;
718 }else if(IsEqualGUID(riid, &IID_IBindCtx)) {
719 TRACE("(%p)->(IID_IBindCtx %p)\n", This, ppv);
720 *ppv = &This->IBindCtx_iface;
721 }else if(IsEqualGUID(riid, &IID_IAsyncBindCtx)) {
722 TRACE("(%p)->(IID_IAsyncBindCtx %p)\n", This, ppv);
723 *ppv = &This->IBindCtx_iface;
724 }
725
726 if(*ppv) {
727 IUnknown_AddRef((IUnknown*)*ppv);
728 return S_OK;
729 }
730
731 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
732 return E_NOINTERFACE;
733 }
734
735 static ULONG WINAPI AsyncBindCtx_AddRef(IBindCtx *iface)
736 {
737 AsyncBindCtx *This = impl_from_IBindCtx(iface);
738 LONG ref = InterlockedIncrement(&This->ref);
739
740 TRACE("(%p) ref=%d\n", This, ref);
741
742 return ref;
743 }
744
745 static ULONG WINAPI AsyncBindCtx_Release(IBindCtx *iface)
746 {
747 AsyncBindCtx *This = impl_from_IBindCtx(iface);
748 LONG ref = InterlockedDecrement(&This->ref);
749
750 TRACE("(%p) ref=%d\n", This, ref);
751
752 if(!ref) {
753 IBindCtx_Release(This->bindctx);
754 heap_free(This);
755 }
756
757 return ref;
758 }
759
760 static HRESULT WINAPI AsyncBindCtx_RegisterObjectBound(IBindCtx *iface, IUnknown *punk)
761 {
762 AsyncBindCtx *This = impl_from_IBindCtx(iface);
763
764 TRACE("(%p)->(%p)\n", This, punk);
765
766 return IBindCtx_RegisterObjectBound(This->bindctx, punk);
767 }
768
769 static HRESULT WINAPI AsyncBindCtx_RevokeObjectBound(IBindCtx *iface, IUnknown *punk)
770 {
771 AsyncBindCtx *This = impl_from_IBindCtx(iface);
772
773 TRACE("(%p %p)\n", This, punk);
774
775 return IBindCtx_RevokeObjectBound(This->bindctx, punk);
776 }
777
778 static HRESULT WINAPI AsyncBindCtx_ReleaseBoundObjects(IBindCtx *iface)
779 {
780 AsyncBindCtx *This = impl_from_IBindCtx(iface);
781
782 TRACE("(%p)\n", This);
783
784 return IBindCtx_ReleaseBoundObjects(This->bindctx);
785 }
786
787 static HRESULT WINAPI AsyncBindCtx_SetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
788 {
789 AsyncBindCtx *This = impl_from_IBindCtx(iface);
790
791 TRACE("(%p)->(%p)\n", This, pbindopts);
792
793 return IBindCtx_SetBindOptions(This->bindctx, pbindopts);
794 }
795
796 static HRESULT WINAPI AsyncBindCtx_GetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
797 {
798 AsyncBindCtx *This = impl_from_IBindCtx(iface);
799
800 TRACE("(%p)->(%p)\n", This, pbindopts);
801
802 return IBindCtx_GetBindOptions(This->bindctx, pbindopts);
803 }
804
805 static HRESULT WINAPI AsyncBindCtx_GetRunningObjectTable(IBindCtx *iface, IRunningObjectTable **pprot)
806 {
807 AsyncBindCtx *This = impl_from_IBindCtx(iface);
808
809 TRACE("(%p)->(%p)\n", This, pprot);
810
811 return IBindCtx_GetRunningObjectTable(This->bindctx, pprot);
812 }
813
814 static HRESULT WINAPI AsyncBindCtx_RegisterObjectParam(IBindCtx *iface, LPOLESTR pszkey, IUnknown *punk)
815 {
816 AsyncBindCtx *This = impl_from_IBindCtx(iface);
817
818 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
819
820 return IBindCtx_RegisterObjectParam(This->bindctx, pszkey, punk);
821 }
822
823 static HRESULT WINAPI AsyncBindCtx_GetObjectParam(IBindCtx* iface, LPOLESTR pszkey, IUnknown **punk)
824 {
825 AsyncBindCtx *This = impl_from_IBindCtx(iface);
826
827 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
828
829 return IBindCtx_GetObjectParam(This->bindctx, pszkey, punk);
830 }
831
832 static HRESULT WINAPI AsyncBindCtx_RevokeObjectParam(IBindCtx *iface, LPOLESTR pszkey)
833 {
834 AsyncBindCtx *This = impl_from_IBindCtx(iface);
835
836 TRACE("(%p)->(%s)\n", This, debugstr_w(pszkey));
837
838 return IBindCtx_RevokeObjectParam(This->bindctx, pszkey);
839 }
840
841 static HRESULT WINAPI AsyncBindCtx_EnumObjectParam(IBindCtx *iface, IEnumString **pszkey)
842 {
843 AsyncBindCtx *This = impl_from_IBindCtx(iface);
844
845 TRACE("(%p)->(%p)\n", This, pszkey);
846
847 return IBindCtx_EnumObjectParam(This->bindctx, pszkey);
848 }
849
850 static const IBindCtxVtbl AsyncBindCtxVtbl =
851 {
852 AsyncBindCtx_QueryInterface,
853 AsyncBindCtx_AddRef,
854 AsyncBindCtx_Release,
855 AsyncBindCtx_RegisterObjectBound,
856 AsyncBindCtx_RevokeObjectBound,
857 AsyncBindCtx_ReleaseBoundObjects,
858 AsyncBindCtx_SetBindOptions,
859 AsyncBindCtx_GetBindOptions,
860 AsyncBindCtx_GetRunningObjectTable,
861 AsyncBindCtx_RegisterObjectParam,
862 AsyncBindCtx_GetObjectParam,
863 AsyncBindCtx_EnumObjectParam,
864 AsyncBindCtx_RevokeObjectParam
865 };
866
867 static HRESULT init_bindctx(IBindCtx *bindctx, DWORD options,
868 IBindStatusCallback *callback, IEnumFORMATETC *format)
869 {
870 BIND_OPTS bindopts;
871 HRESULT hres;
872
873 if(options)
874 FIXME("not supported options %08x\n", options);
875 if(format)
876 FIXME("format is not supported\n");
877
878 bindopts.cbStruct = sizeof(BIND_OPTS);
879 bindopts.grfFlags = BIND_MAYBOTHERUSER;
880 bindopts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
881 bindopts.dwTickCountDeadline = 0;
882
883 hres = IBindCtx_SetBindOptions(bindctx, &bindopts);
884 if(FAILED(hres))
885 return hres;
886
887 if(callback) {
888 hres = RegisterBindStatusCallback(bindctx, callback, NULL, 0);
889 if(FAILED(hres))
890 return hres;
891 }
892
893 return S_OK;
894 }
895
896 /***********************************************************************
897 * CreateAsyncBindCtx (urlmon.@)
898 */
899 HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback,
900 IEnumFORMATETC *format, IBindCtx **pbind)
901 {
902 IBindCtx *bindctx;
903 HRESULT hres;
904
905 TRACE("(%08x %p %p %p)\n", reserved, callback, format, pbind);
906
907 if(!pbind || !callback)
908 return E_INVALIDARG;
909
910 hres = CreateBindCtx(0, &bindctx);
911 if(FAILED(hres))
912 return hres;
913
914 hres = init_bindctx(bindctx, 0, callback, format);
915 if(FAILED(hres)) {
916 IBindCtx_Release(bindctx);
917 return hres;
918 }
919
920 *pbind = bindctx;
921 return S_OK;
922 }
923
924 /***********************************************************************
925 * CreateAsyncBindCtxEx (urlmon.@)
926 *
927 * Create an asynchronous bind context.
928 */
929 HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options,
930 IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx** pbind,
931 DWORD reserved)
932 {
933 AsyncBindCtx *ret;
934 IBindCtx *bindctx;
935 HRESULT hres;
936
937 TRACE("(%p %08x %p %p %p %d)\n", ibind, options, callback, format, pbind, reserved);
938
939 if(!pbind)
940 return E_INVALIDARG;
941
942 if(reserved)
943 WARN("reserved=%d\n", reserved);
944
945 if(ibind) {
946 IBindCtx_AddRef(ibind);
947 bindctx = ibind;
948 }else {
949 hres = CreateBindCtx(0, &bindctx);
950 if(FAILED(hres))
951 return hres;
952 }
953
954 ret = heap_alloc(sizeof(AsyncBindCtx));
955
956 ret->IBindCtx_iface.lpVtbl = &AsyncBindCtxVtbl;
957 ret->ref = 1;
958 ret->bindctx = bindctx;
959
960 hres = init_bindctx(&ret->IBindCtx_iface, options, callback, format);
961 if(FAILED(hres)) {
962 IBindCtx_Release(&ret->IBindCtx_iface);
963 return hres;
964 }
965
966 *pbind = &ret->IBindCtx_iface;
967 return S_OK;
968 }