EnumThemeColors() and EnumThemeSizes() actually do not return a single
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 static const WCHAR TEST_URL_1[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','\0'};
33 static const WCHAR TEST_PART_URL_1[] = {'/','t','e','s','t','/','\0'};
34
35 static const WCHAR WINE_ABOUT_URL[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
36                                        'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
37 static BOOL stopped_binding = FALSE;
38
39 static void test_CreateURLMoniker(LPCWSTR url1, LPCWSTR url2)
40 {
41     HRESULT hr;
42     IMoniker *mon1 = NULL;
43     IMoniker *mon2 = NULL;
44
45     hr = CreateURLMoniker(NULL, url1, &mon1);
46     ok(SUCCEEDED(hr), "failed to create moniker: 0x%08lx\n", hr);
47     if(SUCCEEDED(hr)) {
48         hr = CreateURLMoniker(mon1, url2, &mon2);
49         ok(SUCCEEDED(hr), "failed to create moniker: 0x%08lx\n", hr);
50     }
51     if(mon1) IMoniker_Release(mon1);
52     if(mon2) IMoniker_Release(mon2);
53 }
54
55 static void test_create(void)
56 {
57     test_CreateURLMoniker(TEST_URL_1, TEST_PART_URL_1);
58 }
59
60 typedef struct {
61     const IBindStatusCallbackVtbl *lpVtbl;
62     LONG ref;
63     IBinding *pbind;
64     IStream *pstr;
65 } statusclb;
66
67 static HRESULT WINAPI statusclb_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppvObject)
68 {
69     return E_NOINTERFACE;
70 }
71
72 static ULONG WINAPI statusclb_AddRef(IBindStatusCallback *iface)
73 {
74     return InterlockedIncrement(&((statusclb*)iface)->ref);
75 }
76
77 static ULONG WINAPI statusclb_Release(IBindStatusCallback *iface)
78 {
79     statusclb *This = (statusclb*)iface;
80     ULONG ref;
81     ref = InterlockedDecrement(&This->ref);
82     if(!ref)
83         HeapFree(GetProcessHeap(), 0, This);
84     return ref;
85 }
86
87 static HRESULT WINAPI statusclb_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, IBinding *pib)
88 {
89     statusclb *This = (statusclb*)iface;
90     HRESULT hres;
91     IMoniker *mon;
92
93     This->pbind = pib;
94     ok(pib != NULL, "pib should not be NULL\n");
95     if(pib)
96         IBinding_AddRef(pib);
97
98     hres = IBinding_QueryInterface(pib, &IID_IMoniker, (void**)&mon);
99     ok(hres == E_NOINTERFACE, "IBinding should not have IMoniker interface\n");
100     if(SUCCEEDED(hres))
101         IMoniker_Release(mon);
102
103     return S_OK;
104 }
105
106 static HRESULT WINAPI statusclb_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
107 {
108     return E_NOTIMPL;
109 }
110
111 static HRESULT WINAPI statusclb_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
112 {
113     return E_NOTIMPL;
114 }
115
116 static HRESULT WINAPI statusclb_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, ULONG ulProgressMax,
117                            ULONG ulStatusCode, LPCWSTR szStatusText)
118 {
119     return S_OK;
120 }
121
122 static HRESULT WINAPI statusclb_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
123 {
124     statusclb *This = (statusclb*)iface;
125
126     ok(SUCCEEDED(hresult), "Download failed: %08lx\n", hresult);
127     ok(szError == NULL, "szError should be NULL\n");
128     stopped_binding = TRUE;
129     IBinding_Release(This->pbind);
130     ok(This->pstr != NULL, "pstr should not be NULL here\n");
131     if(This->pstr)
132         IStream_Release(This->pstr);
133
134     return S_OK;
135 }
136
137 static HRESULT WINAPI statusclb_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
138 {
139     DWORD cbSize;
140
141     *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
142     cbSize = pbindinfo->cbSize;
143     memset(pbindinfo, 0, cbSize);
144     pbindinfo->cbSize = cbSize;
145
146     return S_OK;
147 }
148
149 static HRESULT WINAPI statusclb_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF, DWORD dwSize,
150                                                 FORMATETC* pformatetc, STGMEDIUM* pstgmed)
151 {
152     statusclb *This = (statusclb*)iface;
153     HRESULT hres;
154     DWORD readed;
155     BYTE buf[512];
156     if(!This->pstr) {
157         ok(grfBSCF & BSCF_FIRSTDATANOTIFICATION, "pstr should be set when BSCF_FIRSTDATANOTIFICATION\n");
158         This->pstr = U(*pstgmed).pstm;
159         IStream_AddRef(This->pstr);
160         ok(This->pstr != NULL, "pstr should not be NULL here\n");
161     }
162
163     do hres = IStream_Read(This->pstr, buf, 512, &readed);
164     while(hres == S_OK);
165     ok(hres == S_FALSE || hres == E_PENDING, "IStream_Read returned %08lx\n", hres);
166
167     return S_OK;
168 }
169
170 static HRESULT WINAPI statusclb_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
171 {
172     return E_NOTIMPL;
173 }
174
175 static const IBindStatusCallbackVtbl statusclbVtbl = {
176     statusclb_QueryInterface,
177     statusclb_AddRef,
178     statusclb_Release,
179     statusclb_OnStartBinding,
180     statusclb_GetPriority,
181     statusclb_OnLowResource,
182     statusclb_OnProgress,
183     statusclb_OnStopBinding,
184     statusclb_GetBindInfo,
185     statusclb_OnDataAvailable,
186     statusclb_OnObjectAvailable
187 };
188
189 static IBindStatusCallback* statusclb_create(void)
190 {
191     statusclb *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(statusclb));
192     ret->lpVtbl = &statusclbVtbl;
193     ret->ref = 1;
194     ret->pbind = NULL;
195     ret->pstr = NULL;
196     return (IBindStatusCallback*)ret;
197 }
198
199 static void test_CreateAsyncBindCtx(void)
200 {
201     IBindCtx *bctx = (IBindCtx*)0x0ff00ff0;
202     HRESULT hres;
203     ULONG ref;
204     BIND_OPTS bindopts;
205     IBindStatusCallback *bsc = statusclb_create();
206
207     hres = CreateAsyncBindCtx(0, NULL, NULL, &bctx);
208     ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08lx\n", hres);
209     ok(bctx == (IBindCtx*)0x0ff00ff0, "bctx should not be changed\n");
210
211     hres = CreateAsyncBindCtx(0, NULL, NULL, NULL);
212     ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08lx\n", hres);
213
214     hres = CreateAsyncBindCtx(0, bsc, NULL, &bctx);
215     ok(SUCCEEDED(hres), "CreateAsyncBindCtx failed: %08lx\n", hres);
216     if(FAILED(hres)) {
217         IBindStatusCallback_Release(bsc);
218         return;
219     }
220
221     bindopts.cbStruct = 16;
222     hres = IBindCtx_GetBindOptions(bctx, &bindopts);
223     ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08lx\n", hres);
224     ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
225                 "bindopts.grfFlags = %08lx, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
226     ok(bindopts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
227                 "bindopts.grfMode = %08lx, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n", bindopts.grfMode);
228     ok(bindopts.dwTickCountDeadline == 0,
229                 "bindopts.dwTickCountDeadline = %08lx, expected: 0\n", bindopts.dwTickCountDeadline);
230
231     ref = IBindCtx_Release(bctx);
232     ok(ref == 0, "bctx should be destroyed here\n");
233     ref = IBindStatusCallback_Release(bsc);
234     ok(ref == 0, "bsc should be destroyed here\n");
235 }
236
237 static void test_BindToStorage(void)
238 {
239     IMoniker *mon;
240     HRESULT hres;
241     LPOLESTR display_name;
242     IBindCtx *bctx;
243     MSG msg;
244     IBindStatusCallback *previousclb, *sclb = statusclb_create();
245     IUnknown *unk = (IUnknown*)0x00ff00ff;
246     IBinding *bind;
247
248     hres = CreateAsyncBindCtx(0, sclb, NULL, &bctx);
249     ok(SUCCEEDED(hres), "CreateAsyncBindCtx failed: %08lx\n\n", hres);
250     if(FAILED(hres)) {
251         IBindStatusCallback_Release(sclb);
252         return;
253     }
254
255     hres = RegisterBindStatusCallback(bctx, sclb, &previousclb, 0);
256     ok(SUCCEEDED(hres), "RegisterBindStatusCallback failed: %08lx\n", hres);
257     ok(previousclb == sclb, "previousclb(%p) != sclb(%p)\n", previousclb, sclb);
258     if(previousclb)
259         IBindStatusCallback_Release(previousclb);
260
261     hres = CreateURLMoniker(NULL, WINE_ABOUT_URL, &mon);
262     ok(SUCCEEDED(hres), "failed to create moniker: %08lx\n", hres);
263     if(FAILED(hres)) {
264         IBindStatusCallback_Release(sclb);
265         IBindCtx_Release(bctx);
266         return;
267     }
268
269     hres = IMoniker_QueryInterface(mon, &IID_IBinding, (void**)&bind);
270     ok(hres == E_NOINTERFACE, "IMoniker should not have IBinding interface\n");
271     if(SUCCEEDED(hres))
272         IBinding_Release(bind);
273
274     hres = IMoniker_GetDisplayName(mon, bctx, NULL, &display_name);
275     ok(SUCCEEDED(hres), "GetDisplayName failed %08lx\n", hres);
276     ok(!lstrcmpW(display_name, WINE_ABOUT_URL), "GetDisplayName got wrong name\n");
277
278     hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk);
279     ok(SUCCEEDED(hres), "IMoniker_BindToStorage failed: %08lx\n", hres);
280     todo_wine {
281         ok(unk == NULL, "istr should be NULL\n");
282     }
283     if(FAILED(hres)) {
284         IBindStatusCallback_Release(sclb);
285         IMoniker_Release(mon);
286         return;
287     }
288     if(unk)
289         IUnknown_Release(unk);
290
291     while(!stopped_binding && GetMessage(&msg,NULL,0,0)) {
292         TranslateMessage(&msg);
293         DispatchMessage(&msg);
294     }
295
296     ok(IMoniker_Release(mon) == 0, "mon should be destroyed here\n");
297     ok(IBindCtx_Release(bctx) == 0, "bctx should be destroyed here\n");
298     ok(IBindStatusCallback_Release(sclb) == 0, "scbl should be destroyed here\n");
299 }
300
301 START_TEST(url)
302 {
303     test_create();
304     test_CreateAsyncBindCtx();
305     test_BindToStorage();
306 }