query: Add a stub implementation for LocateCatalogs.
[wine] / dlls / urlmon / tests / url.c
1 /*
2  * UrlMon URL tests
3  *
4  * Copyright 2004 Kevin Koltzau
5  * Copyright 2004 Jacek Caban
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "urlmon.h"
29
30 #include "wine/test.h"
31
32 #define DEFINE_EXPECT(func) \
33     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34
35 #define SET_EXPECT(func) \
36     expect_ ## func = TRUE
37
38 #define CHECK_EXPECT(func) \
39     do { \
40         ok(expect_ ##func, "unexpected call " #func "\n"); \
41         expect_ ## func = FALSE; \
42         called_ ## func = TRUE; \
43     }while(0)
44
45 #define CHECK_EXPECT2(func) \
46     do { \
47         ok(expect_ ##func, "unexpected call " #func "\n"); \
48         called_ ## func = TRUE; \
49     }while(0)
50
51 #define CHECK_CALLED(func) \
52     do { \
53         ok(called_ ## func, "expected " #func "\n"); \
54         expect_ ## func = called_ ## func = FALSE; \
55     }while(0)
56
57 DEFINE_EXPECT(GetBindInfo);
58 DEFINE_EXPECT(OnStartBinding);
59 DEFINE_EXPECT(OnProgress_FINDINGRESOURCE);
60 DEFINE_EXPECT(OnProgress_CONNECTING);
61 DEFINE_EXPECT(OnProgress_SENDINGREQUEST);
62 DEFINE_EXPECT(OnProgress_MIMETYPEAVAILABLE);
63 DEFINE_EXPECT(OnProgress_BEGINDOWNLOADDATA);
64 DEFINE_EXPECT(OnProgress_DOWNLOADINGDATA);
65 DEFINE_EXPECT(OnProgress_ENDDOWNLOADDATA);
66 DEFINE_EXPECT(OnStopBinding);
67 DEFINE_EXPECT(OnDataAvailable);
68 DEFINE_EXPECT(Start);
69 DEFINE_EXPECT(Read);
70 DEFINE_EXPECT(LockRequest);
71 DEFINE_EXPECT(Terminate);
72 DEFINE_EXPECT(UnlockRequest);
73
74 static const WCHAR TEST_URL_1[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','\0'};
75 static const WCHAR TEST_PART_URL_1[] = {'/','t','e','s','t','/','\0'};
76
77 static const WCHAR WINE_ABOUT_URL[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
78                                        'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
79 static const WCHAR ABOUT_BLANK[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
80 static WCHAR INDEX_HTML[MAX_PATH];
81
82 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
83
84 static BOOL stopped_binding = FALSE, emulate_protocol = FALSE;
85 static DWORD read = 0;
86
87 static const LPCWSTR urls[] = {
88     WINE_ABOUT_URL,
89     ABOUT_BLANK,
90     INDEX_HTML
91 };
92
93 static enum {
94     HTTP_TEST,
95     ABOUT_TEST,
96     FILE_TEST
97 } test_protocol;
98
99 static void test_CreateURLMoniker(LPCWSTR url1, LPCWSTR url2)
100 {
101     HRESULT hr;
102     IMoniker *mon1 = NULL;
103     IMoniker *mon2 = NULL;
104
105     hr = CreateURLMoniker(NULL, url1, &mon1);
106     ok(SUCCEEDED(hr), "failed to create moniker: 0x%08lx\n", hr);
107     if(SUCCEEDED(hr)) {
108         hr = CreateURLMoniker(mon1, url2, &mon2);
109         ok(SUCCEEDED(hr), "failed to create moniker: 0x%08lx\n", hr);
110     }
111     if(mon1) IMoniker_Release(mon1);
112     if(mon2) IMoniker_Release(mon2);
113 }
114
115 static void test_create(void)
116 {
117     test_CreateURLMoniker(TEST_URL_1, TEST_PART_URL_1);
118 }
119
120 static HRESULT WINAPI Protocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
121 {
122     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
123         *ppv = iface;
124         return S_OK;
125     }
126
127     *ppv = NULL;
128     return E_NOINTERFACE;
129 }
130
131 static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface)
132 {
133     return 2;
134 }
135
136 static ULONG WINAPI Protocol_Release(IInternetProtocol *iface)
137 {
138     return 1;
139 }
140
141 static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
142         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
143         DWORD grfPI, DWORD dwReserved)
144 {
145     BINDINFO bindinfo, bi = {sizeof(bi), 0};
146     DWORD bindf, bscf = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION;
147     WCHAR null_char = 0;
148     HRESULT hres;
149
150     static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
151
152     CHECK_EXPECT(Start);
153
154     read = 0;
155
156     ok(szUrl && !lstrcmpW(szUrl, urls[test_protocol]), "wrong url\n");
157     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
158     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
159     ok(grfPI == 0, "grfPI=%ld, expected 0\n", grfPI);
160     ok(dwReserved == 0, "dwReserved=%ld, expected 0\n", dwReserved);
161
162     memset(&bindinfo, 0, sizeof(bindinfo));
163     bindinfo.cbSize = sizeof(bindinfo);
164     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo);
165     ok(hres == S_OK, "GetBindInfo failed: %08lx\n", hres);
166
167     if(test_protocol == FILE_TEST) {
168         ok(bindf == (BINDF_ASYNCHRONOUS|BINDF_ASYNCSTORAGE|BINDF_PULLDATA
169                      |BINDF_FROMURLMON),
170            "bindf=%08lx\n", bindf);
171     }else {
172         ok(bindf == (BINDF_ASYNCHRONOUS|BINDF_ASYNCSTORAGE|BINDF_PULLDATA|
173                      BINDF_FROMURLMON|BINDF_NEEDFILE),
174            "bindf=%08lx\n", bindf);
175     }
176
177     ok(!memcmp(&bindinfo, &bi, sizeof(bindinfo)), "wrong bindinfo\n");
178
179     if(test_protocol == FILE_TEST) {
180         SET_EXPECT(OnProgress_SENDINGREQUEST);
181         hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
182                 BINDSTATUS_SENDINGREQUEST, &null_char);
183         ok(hres == S_OK,
184            "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08lx\n", hres);
185         CHECK_CALLED(OnProgress_SENDINGREQUEST);
186
187         hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
188                 BINDSTATUS_CACHEFILENAMEAVAILABLE, &null_char);
189         ok(hres == S_OK,
190            "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08lx\n", hres);
191
192         SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
193         hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
194                 BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, wszTextHtml);
195         ok(hres == S_OK,
196            "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08lx\n", hres);
197         CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
198     }else {
199         hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
200                 BINDSTATUS_MIMETYPEAVAILABLE, wszTextHtml);
201         ok(hres == S_OK,
202            "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08lx\n", hres);
203     }
204
205     if(test_protocol == ABOUT_TEST)
206         bscf |= BSCF_DATAFULLYAVAILABLE;
207
208     SET_EXPECT(Read);
209     if(test_protocol != FILE_TEST)
210         SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
211     SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
212     SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
213     SET_EXPECT(LockRequest);
214     SET_EXPECT(OnDataAvailable);
215     SET_EXPECT(OnStopBinding);
216
217     hres = IInternetProtocolSink_ReportData(pOIProtSink, bscf, 13, 13);
218     ok(hres == S_OK, "ReportData failed: %08lx\n", hres);
219
220     CHECK_CALLED(Read);
221     if(test_protocol != FILE_TEST)
222         CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
223     CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
224     CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
225     CHECK_CALLED(LockRequest);
226     CHECK_CALLED(OnDataAvailable);
227     CHECK_CALLED(OnStopBinding);
228
229     SET_EXPECT(Terminate);
230     hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
231     ok(hres == S_OK, "ReportResult failed: %08lx\n", hres);
232     CHECK_CALLED(Terminate);
233
234     return S_OK;
235 }
236
237 static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface,
238         PROTOCOLDATA *pProtocolData)
239 {
240     ok(0, "unexpected call\n");
241     return E_NOTIMPL;
242 }
243
244 static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
245         DWORD dwOptions)
246 {
247     ok(0, "unexpected call\n");
248     return E_NOTIMPL;
249 }
250
251 static HRESULT WINAPI Protocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
252 {
253     CHECK_EXPECT(Terminate);
254     ok(dwOptions == 0, "dwOptions=%ld, expected 0\n", dwOptions);
255     return S_OK;
256 }
257
258 static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface)
259 {
260     ok(0, "unexpected call\n");
261     return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface)
265 {
266     ok(0, "unexpected call\n");
267     return E_NOTIMPL;
268 }
269
270 static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv,
271         ULONG cb, ULONG *pcbRead)
272 {
273     static const char data[] = "<HTML></HTML>";
274
275     CHECK_EXPECT2(Read);
276
277     if(read) {
278         *pcbRead = 0;
279         return S_FALSE;
280     }
281
282     ok(pv != NULL, "pv == NULL\n");
283     ok(cb != 0, "cb == 0\n");
284     ok(pcbRead != NULL, "pcbRead == NULL\n");
285     if(pcbRead) {
286         ok(*pcbRead == 0, "*pcbRead=%ld, expected 0\n", *pcbRead);
287         *pcbRead = 13;
288         read = 13;
289     }
290     if(pv)
291         memcpy(pv, data, sizeof(data));
292
293     return S_OK;
294 }
295
296 static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface,
297         LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
298 {
299     ok(0, "unexpected call\n");
300     return E_NOTIMPL;
301 }
302
303 static HRESULT WINAPI Protocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
304 {
305     CHECK_EXPECT(LockRequest);
306     return S_OK;
307 }
308
309 static HRESULT WINAPI Protocol_UnlockRequest(IInternetProtocol *iface)
310 {
311     CHECK_EXPECT(UnlockRequest);
312     return S_OK;
313 }
314
315 static const IInternetProtocolVtbl ProtocolVtbl = {
316     Protocol_QueryInterface,
317     Protocol_AddRef,
318     Protocol_Release,
319     Protocol_Start,
320     Protocol_Continue,
321     Protocol_Abort,
322     Protocol_Terminate,
323     Protocol_Suspend,
324     Protocol_Resume,
325     Protocol_Read,
326     Protocol_Seek,
327     Protocol_LockRequest,
328     Protocol_UnlockRequest
329 };
330
331 static IInternetProtocol Protocol = { &ProtocolVtbl };
332
333 static HRESULT WINAPI statusclb_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
334 {
335     if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
336         if(emulate_protocol) {
337             *ppv = &Protocol;
338             return S_OK;
339         }else {
340             return E_NOINTERFACE;
341         }
342     }
343
344     return E_NOINTERFACE;
345 }
346
347 static ULONG WINAPI statusclb_AddRef(IBindStatusCallback *iface)
348 {
349     return 2;
350 }
351
352 static ULONG WINAPI statusclb_Release(IBindStatusCallback *iface)
353 {
354     return 1;
355 }
356
357 static HRESULT WINAPI statusclb_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
358         IBinding *pib)
359 {
360     HRESULT hres;
361     IMoniker *mon;
362
363     CHECK_EXPECT(OnStartBinding);
364
365     ok(pib != NULL, "pib should not be NULL\n");
366
367     hres = IBinding_QueryInterface(pib, &IID_IMoniker, (void**)&mon);
368     ok(hres == E_NOINTERFACE, "IBinding should not have IMoniker interface\n");
369     if(SUCCEEDED(hres))
370         IMoniker_Release(mon);
371
372     return S_OK;
373 }
374
375 static HRESULT WINAPI statusclb_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
376 {
377     ok(0, "unexpected call\n");
378     return E_NOTIMPL;
379 }
380
381 static HRESULT WINAPI statusclb_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
382 {
383     ok(0, "unexpected call\n");
384     return E_NOTIMPL;
385 }
386
387 static HRESULT WINAPI statusclb_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
388         ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
389 {
390     switch(ulStatusCode) {
391     case BINDSTATUS_FINDINGRESOURCE:
392         CHECK_EXPECT(OnProgress_FINDINGRESOURCE);
393         break;
394     case BINDSTATUS_CONNECTING:
395         CHECK_EXPECT(OnProgress_CONNECTING);
396         break;
397     case BINDSTATUS_SENDINGREQUEST:
398         CHECK_EXPECT(OnProgress_SENDINGREQUEST);
399         break;
400     case BINDSTATUS_MIMETYPEAVAILABLE:
401         CHECK_EXPECT(OnProgress_MIMETYPEAVAILABLE);
402         break;
403     case BINDSTATUS_BEGINDOWNLOADDATA:
404         CHECK_EXPECT(OnProgress_BEGINDOWNLOADDATA);
405         ok(szStatusText != NULL, "szStatusText == NULL\n");
406         if(szStatusText)
407             ok(!lstrcmpW(szStatusText, urls[test_protocol]), "wrong szStatusText\n");
408         break;
409     case BINDSTATUS_DOWNLOADINGDATA:
410         CHECK_EXPECT2(OnProgress_DOWNLOADINGDATA);
411         break;
412     case BINDSTATUS_ENDDOWNLOADDATA:
413         CHECK_EXPECT(OnProgress_ENDDOWNLOADDATA);
414         ok(szStatusText != NULL, "szStatusText == NULL\n");
415         if(szStatusText)
416             ok(!lstrcmpW(szStatusText, urls[test_protocol]), "wrong szStatusText\n");
417         break;
418     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
419         ok(szStatusText != NULL, "szStatusText == NULL\n");
420         if(szStatusText && test_protocol == FILE_TEST)
421             ok(!lstrcmpW(INDEX_HTML+7, szStatusText), "wrong szStatusText\n");
422         break;
423     default:
424         todo_wine { ok(0, "unexpexted code %ld\n", ulStatusCode); }
425     };
426     return S_OK;
427 }
428
429 static HRESULT WINAPI statusclb_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
430 {
431     CHECK_EXPECT(OnStopBinding);
432
433     ok(SUCCEEDED(hresult), "Download failed: %08lx\n", hresult);
434     ok(szError == NULL, "szError should be NULL\n");
435     stopped_binding = TRUE;
436
437     return S_OK;
438 }
439
440 static HRESULT WINAPI statusclb_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
441 {
442     DWORD cbSize;
443
444     CHECK_EXPECT(GetBindInfo);
445
446     *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
447     cbSize = pbindinfo->cbSize;
448     memset(pbindinfo, 0, cbSize);
449     pbindinfo->cbSize = cbSize;
450
451     return S_OK;
452 }
453
454 static HRESULT WINAPI statusclb_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
455         DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
456 {
457     HRESULT hres;
458     DWORD readed;
459     BYTE buf[512];
460
461     CHECK_EXPECT2(OnDataAvailable);
462
463 #if 0 /* Uncomment after removing BindToStorage hack. */
464     ok(pformatetc != NULL, "pformatetx == NULL\n");
465     if(pformatetc) {
466         ok(pformatetc->cfFormat == 0xc02d, "clipformat=%x\n", pformatetc->cfFormat); 
467         ok(pformatetc->ptd == NULL, "ptd = %p\n", pformatetc->ptd);
468         ok(pformatetc->dwAspect == 1, "dwAspect=%ld\n", pformatetc->dwAspect);
469         ok(pformatetc->lindex == -1, "lindex=%ld\n", pformatetc->lindex);
470         ok(pformatetc->tymed == TYMED_ISTREAM, "tymed=%ld\n", pformatetc->tymed);
471     }
472
473     ok(pstgmed != NULL, "stgmeg == NULL\n");
474     if(pstgmed) {
475         ok(pstgmed->tymed == TYMED_ISTREAM, "tymed=%ld\n", pstgmed->tymed);
476         ok(U(*pstgmed).pstm != NULL, "pstm == NULL\n");
477         ok(pstgmed->pUnkForRelease != NULL, "pUnkForRelease == NULL\n");
478     }
479 #endif
480
481     if(U(*pstgmed).pstm) {
482         do hres = IStream_Read(U(*pstgmed).pstm, buf, 512, &readed);
483         while(hres == S_OK);
484         ok(hres == S_FALSE || hres == E_PENDING, "IStream_Read returned %08lx\n", hres);
485     }
486
487     return S_OK;
488 }
489
490 static HRESULT WINAPI statusclb_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
491 {
492     ok(0, "unexpected call\n");
493     return E_NOTIMPL;
494 }
495
496 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
497     statusclb_QueryInterface,
498     statusclb_AddRef,
499     statusclb_Release,
500     statusclb_OnStartBinding,
501     statusclb_GetPriority,
502     statusclb_OnLowResource,
503     statusclb_OnProgress,
504     statusclb_OnStopBinding,
505     statusclb_GetBindInfo,
506     statusclb_OnDataAvailable,
507     statusclb_OnObjectAvailable
508 };
509
510 static IBindStatusCallback bsc = { &BindStatusCallbackVtbl };
511
512 static void test_CreateAsyncBindCtx(void)
513 {
514     IBindCtx *bctx = (IBindCtx*)0x0ff00ff0;
515     HRESULT hres;
516     ULONG ref;
517     BIND_OPTS bindopts;
518
519     hres = CreateAsyncBindCtx(0, NULL, NULL, &bctx);
520     ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08lx\n", hres);
521     ok(bctx == (IBindCtx*)0x0ff00ff0, "bctx should not be changed\n");
522
523     hres = CreateAsyncBindCtx(0, NULL, NULL, NULL);
524     ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08lx\n", hres);
525
526     hres = CreateAsyncBindCtx(0, &bsc, NULL, &bctx);
527     ok(SUCCEEDED(hres), "CreateAsyncBindCtx failed: %08lx\n", hres);
528
529     bindopts.cbStruct = sizeof(bindopts);
530     hres = IBindCtx_GetBindOptions(bctx, &bindopts);
531     ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08lx\n", hres);
532     ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
533                 "bindopts.grfFlags = %08lx, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
534     ok(bindopts.grfMode == (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
535                 "bindopts.grfMode = %08lx, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
536                 bindopts.grfMode);
537     ok(bindopts.dwTickCountDeadline == 0,
538                 "bindopts.dwTickCountDeadline = %08lx, expected: 0\n", bindopts.dwTickCountDeadline);
539
540     ref = IBindCtx_Release(bctx);
541     ok(ref == 0, "bctx should be destroyed here\n");
542 }
543
544 static void test_CreateAsyncBindCtxEx(void)
545 {
546     IBindCtx *bctx = NULL, *bctx_arg = NULL;
547     BIND_OPTS bindopts;
548     HRESULT hres;
549
550     hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, NULL, 0);
551     ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed: %08lx, expected E_INVALIDARG\n", hres);
552
553     hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &bctx, 0);
554     ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08lx\n", hres);
555
556     if(SUCCEEDED(hres)) {
557         bindopts.cbStruct = sizeof(bindopts);
558         hres = IBindCtx_GetBindOptions(bctx, &bindopts);
559         ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08lx\n", hres);
560         ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
561                 "bindopts.grfFlags = %08lx, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
562         ok(bindopts.grfMode == (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
563                 "bindopts.grfMode = %08lx, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
564                 bindopts.grfMode);
565         ok(bindopts.dwTickCountDeadline == 0,
566                 "bindopts.dwTickCountDeadline = %08lx, expected: 0\n", bindopts.dwTickCountDeadline);
567
568         IBindCtx_Release(bctx);
569     }
570
571     CreateBindCtx(0, &bctx_arg);
572     hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &bctx, 0);
573     ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08lx\n", hres);
574
575     if(SUCCEEDED(hres)) {
576         bindopts.cbStruct = sizeof(bindopts);
577         hres = IBindCtx_GetBindOptions(bctx, &bindopts);
578         ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08lx\n", hres);
579         ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
580                 "bindopts.grfFlags = %08lx, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
581         ok(bindopts.grfMode == (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
582                 "bindopts.grfMode = %08lx, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
583                 bindopts.grfMode);
584         ok(bindopts.dwTickCountDeadline == 0,
585                 "bindopts.dwTickCountDeadline = %08lx, expected: 0\n", bindopts.dwTickCountDeadline);
586
587         IBindCtx_Release(bctx);
588     }
589
590     IBindCtx_Release(bctx_arg);
591
592     hres = CreateAsyncBindCtxEx(NULL, 0, &bsc, NULL, &bctx, 0);
593     ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08lx\n", hres);
594
595     if(SUCCEEDED(hres))
596         IBindCtx_Release(bctx);
597 }
598
599 static void test_BindToStorage(void)
600 {
601     IMoniker *mon;
602     HRESULT hres;
603     LPOLESTR display_name;
604     IBindCtx *bctx;
605     MSG msg;
606     IBindStatusCallback *previousclb;
607     IUnknown *unk = (IUnknown*)0x00ff00ff;
608     IBinding *bind;
609
610     hres = CreateAsyncBindCtx(0, &bsc, NULL, &bctx);
611     ok(SUCCEEDED(hres), "CreateAsyncBindCtx failed: %08lx\n\n", hres);
612     if(FAILED(hres))
613         return;
614
615     hres = RegisterBindStatusCallback(bctx, &bsc, &previousclb, 0);
616     ok(SUCCEEDED(hres), "RegisterBindStatusCallback failed: %08lx\n", hres);
617     ok(previousclb == &bsc, "previousclb(%p) != sclb(%p)\n", previousclb, &bsc);
618     if(previousclb)
619         IBindStatusCallback_Release(previousclb);
620
621     hres = CreateURLMoniker(NULL, urls[test_protocol], &mon);
622     ok(SUCCEEDED(hres), "failed to create moniker: %08lx\n", hres);
623     if(FAILED(hres)) {
624         IBindCtx_Release(bctx);
625         return;
626     }
627
628     if(test_protocol == FILE_TEST && INDEX_HTML[7] == '/')
629         memmove(INDEX_HTML+7, INDEX_HTML+8, lstrlenW(INDEX_HTML+7)*sizeof(WCHAR));
630
631     hres = IMoniker_QueryInterface(mon, &IID_IBinding, (void**)&bind);
632     ok(hres == E_NOINTERFACE, "IMoniker should not have IBinding interface\n");
633     if(SUCCEEDED(hres))
634         IBinding_Release(bind);
635
636     hres = IMoniker_GetDisplayName(mon, bctx, NULL, &display_name);
637     ok(hres == S_OK, "GetDisplayName failed %08lx\n", hres);
638     ok(!lstrcmpW(display_name, urls[test_protocol]), "GetDisplayName got wrong name\n");
639
640     SET_EXPECT(GetBindInfo);
641     SET_EXPECT(OnStartBinding);
642     if(emulate_protocol) {
643         SET_EXPECT(Start);
644         SET_EXPECT(UnlockRequest);
645     }else {
646         if(test_protocol == HTTP_TEST) {
647             SET_EXPECT(OnProgress_FINDINGRESOURCE);
648             SET_EXPECT(OnProgress_CONNECTING);
649         }
650         if(test_protocol == HTTP_TEST || test_protocol == FILE_TEST)
651             SET_EXPECT(OnProgress_SENDINGREQUEST);
652         SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
653         SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
654         SET_EXPECT(OnDataAvailable);
655         if(test_protocol == HTTP_TEST)
656             SET_EXPECT(OnProgress_DOWNLOADINGDATA);
657         SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
658         SET_EXPECT(OnStopBinding);
659     }
660
661     hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk);
662     ok(SUCCEEDED(hres), "IMoniker_BindToStorage failed: %08lx\n", hres);
663     if (!SUCCEEDED(hres)) return;
664
665     if(test_protocol == HTTP_TEST) {
666         todo_wine {
667             ok(unk == NULL, "istr should be NULL\n");
668         }
669     }else {
670         ok(unk != NULL, "unk == NULL\n");
671     }
672     if(unk)
673         IUnknown_Release(unk);
674
675     while(!stopped_binding && GetMessage(&msg,NULL,0,0)) {
676         TranslateMessage(&msg);
677         DispatchMessage(&msg);
678     }
679
680     CHECK_CALLED(GetBindInfo);
681     CHECK_CALLED(OnStartBinding);
682     if(emulate_protocol) {
683         CHECK_CALLED(Start);
684         CHECK_CALLED(UnlockRequest);
685     }else {
686         if(test_protocol == HTTP_TEST) {
687             CHECK_CALLED(OnProgress_FINDINGRESOURCE);
688             CHECK_CALLED(OnProgress_CONNECTING);
689             CHECK_CALLED(OnProgress_SENDINGREQUEST);
690             todo_wine { CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE); }
691         }else {
692             CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
693         }
694         CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
695         CHECK_CALLED(OnDataAvailable);
696         if(test_protocol == HTTP_TEST)
697             CHECK_CALLED(OnProgress_DOWNLOADINGDATA);
698         CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
699         CHECK_CALLED(OnStopBinding);
700     }
701
702     ok(IMoniker_Release(mon) == 0, "mon should be destroyed here\n");
703     ok(IBindCtx_Release(bctx) == 0, "bctx should be destroyed here\n");
704 }
705
706 static void set_file_url(void)
707 {
708     int len;
709
710     static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'};
711
712     memcpy(INDEX_HTML, wszFile, sizeof(wszFile));
713     len = sizeof(wszFile)/sizeof(WCHAR);
714     INDEX_HTML[len++] = '/';
715     len += GetCurrentDirectoryW(sizeof(INDEX_HTML)/sizeof(WCHAR)-len, INDEX_HTML+len);
716     INDEX_HTML[len++] = '\\';
717     memcpy(INDEX_HTML+len, wszIndexHtml, sizeof(wszIndexHtml));
718 }
719
720 static void create_file(void)
721 {
722     HANDLE file;
723     DWORD size;
724
725     static const char html_doc[] = "<HTML></HTML>";
726
727     file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
728             FILE_ATTRIBUTE_NORMAL, NULL);
729     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
730     if(file == INVALID_HANDLE_VALUE)
731         return;
732
733     WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
734     CloseHandle(file);
735
736     set_file_url();
737 }
738
739 static void test_BindToStorage_fail(void)
740 {
741     IMoniker *mon = NULL;
742     IBindCtx *bctx = NULL;
743     IUnknown *unk;
744     HRESULT hres;
745
746     hres = CreateURLMoniker(NULL, ABOUT_BLANK, &mon);
747     ok(hres == S_OK, "CreateURLMoniker failed: %08lx\n", hres);
748     if(FAILED(hres))
749         return;
750
751     hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &bctx, 0);
752     ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08lx\n", hres);
753
754     hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk);
755     ok(hres == MK_E_SYNTAX, "hres=%08lx, expected INET_E_SYNTAX\n", hres);
756
757     IBindCtx_Release(bctx);
758
759     IMoniker_Release(mon);
760 }
761
762 START_TEST(url)
763 {
764     test_create();
765     test_CreateAsyncBindCtx();
766     test_CreateAsyncBindCtxEx();
767
768     trace("http test...\n");
769     emulate_protocol = FALSE;
770     test_protocol = HTTP_TEST;
771     test_BindToStorage();
772
773     trace("about test...\n");
774     test_protocol = ABOUT_TEST;
775     CoInitialize(NULL);
776     test_BindToStorage();
777     CoUninitialize();
778
779     trace("emulated about test...\n");
780     emulate_protocol = TRUE;
781     test_protocol = ABOUT_TEST;
782     test_BindToStorage();
783
784     trace("file test...\n");
785     create_file();
786     emulate_protocol = FALSE;
787     test_protocol = FILE_TEST;
788     test_BindToStorage();
789     DeleteFileW(wszIndexHtml);
790
791     trace("emulated file test...\n");
792     set_file_url();
793     emulate_protocol = TRUE;
794     test_protocol = FILE_TEST;
795     test_BindToStorage();
796
797     test_BindToStorage_fail();
798 }