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