[SHDOCVW_WINETEST] Sync with Wine Staging 3.3. CORE-14434
[reactos.git] / modules / rostests / winetests / shdocvw / shdocvw.c
1 /*
2 * Unit tests for misc shdocvw functions
3 *
4 * Copyright 2008 Detlef Riekenberg
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winreg.h"
27 #include "wininet.h"
28 #include "winnls.h"
29
30 #include "wine/test.h"
31
32 /* ################ */
33
34 static HMODULE hshdocvw;
35 static HRESULT (WINAPI *pURLSubRegQueryA)(LPCSTR, LPCSTR, DWORD, LPVOID, DWORD, DWORD);
36 static DWORD (WINAPI *pParseURLFromOutsideSourceA)(LPCSTR, LPSTR, LPDWORD, LPDWORD);
37 static DWORD (WINAPI *pParseURLFromOutsideSourceW)(LPCWSTR, LPWSTR, LPDWORD, LPDWORD);
38
39 static const char appdata[] = "AppData";
40 static const char common_appdata[] = "Common AppData";
41 static const char default_page_url[] = "Default_Page_URL";
42 static const char does_not_exist[] = "does_not_exist";
43 static const char regpath_iemain[] = "Software\\Microsoft\\Internet Explorer\\Main";
44 static const char regpath_shellfolders[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
45 static const char start_page[] = "Start Page";
46
47 /* ################ */
48
49 static const struct {
50 const char *url;
51 const char *newurl;
52 DWORD len;
53 } ParseURL_table[] = {
54 {"http://www.winehq.org", "http://www.winehq.org/", 22},
55 {"www.winehq.org", "http://www.winehq.org/", 22},
56 {"winehq.org", "http://winehq.org/", 18},
57 {"ftp.winehq.org", "ftp://ftp.winehq.org/", 21},
58 {"http://winehq.org", "http://winehq.org/", 18},
59 {"https://winehq.org", "https://winehq.org/", 19},
60 {"https://www.winehq.org", "https://www.winehq.org/", 23},
61 {"ftp://winehq.org", "ftp://winehq.org/", 17},
62 {"ftp://ftp.winehq.org", "ftp://ftp.winehq.org/", 21},
63 {"about:blank", "about:blank", 11},
64 {"about:home", "about:home", 10},
65 {"about:mozilla", "about:mozilla", 13},
66 /* a space at the start is not allowed */
67 {" http://www.winehq.org", "http://%20http://www.winehq.org", 31}
68
69 };
70
71 /* ################ */
72
73 static void init_functions(void)
74 {
75 hshdocvw = LoadLibraryA("shdocvw.dll");
76 pURLSubRegQueryA = (void *) GetProcAddress(hshdocvw, (LPSTR) 151);
77 pParseURLFromOutsideSourceA = (void *) GetProcAddress(hshdocvw, (LPSTR) 169);
78 pParseURLFromOutsideSourceW = (void *) GetProcAddress(hshdocvw, (LPSTR) 170);
79 }
80
81 /* ################ */
82
83 static void test_URLSubRegQueryA(void)
84 {
85 CHAR buffer[INTERNET_MAX_URL_LENGTH];
86 HRESULT hr;
87 DWORD used;
88 DWORD len;
89
90 if (!pURLSubRegQueryA) {
91 skip("URLSubRegQueryA not found\n");
92 return;
93 }
94
95 memset(buffer, '#', sizeof(buffer)-1);
96 buffer[sizeof(buffer)-1] = '\0';
97 /* called by inetcpl.cpl */
98 hr = pURLSubRegQueryA(regpath_iemain, default_page_url, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
99 ok(hr == E_FAIL || hr == S_OK, "got 0x%x (expected E_FAIL or S_OK)\n", hr);
100
101 memset(buffer, '#', sizeof(buffer)-1);
102 buffer[sizeof(buffer)-1] = '\0';
103 /* called by inetcpl.cpl */
104 hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
105 len = lstrlenA(buffer);
106 /* respect privacy: do not dump the url */
107 ok(hr == S_OK, "got 0x%x and %d (expected S_OK)\n", hr, len);
108
109 /* test buffer length: just large enough */
110 memset(buffer, '#', sizeof(buffer)-1);
111 buffer[sizeof(buffer)-1] = '\0';
112 hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, len+1, -1);
113 used = lstrlenA(buffer);
114 /* respect privacy: do not dump the url */
115 ok((hr == S_OK) && (used == len),
116 "got 0x%x and %d (expected S_OK and %d)\n", hr, used, len);
117
118 /* no space for terminating 0: result is truncated */
119 memset(buffer, '#', sizeof(buffer)-1);
120 buffer[sizeof(buffer)-1] = '\0';
121 hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, len, -1);
122 used = lstrlenA(buffer);
123 ok((hr == S_OK) && (used == len - 1),
124 "got 0x%x and %d (expected S_OK and %d)\n", hr, used, len - 1);
125
126 /* no space for the complete result: truncate another char */
127 if (len > 1) {
128 memset(buffer, '#', sizeof(buffer)-1);
129 buffer[sizeof(buffer)-1] = '\0';
130 hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, len-1, -1);
131 used = lstrlenA(buffer);
132 ok((hr == S_OK) && (used == (len - 2)),
133 "got 0x%x and %d (expected S_OK and %d)\n", hr, used, len - 2);
134 }
135
136 /* only space for the terminating 0: function still succeeded */
137 memset(buffer, '#', sizeof(buffer)-1);
138 buffer[sizeof(buffer)-1] = '\0';
139 hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, 1, -1);
140 used = lstrlenA(buffer);
141 ok((hr == S_OK) && !used,
142 "got 0x%x and %d (expected S_OK and 0)\n", hr, used);
143
144 /* size of buffer is 0, but the function still succeed.
145 buffer[0] is cleared in IE 5.01 and IE 5.5 (Buffer Overflow) */
146 memset(buffer, '#', sizeof(buffer)-1);
147 buffer[sizeof(buffer)-1] = '\0';
148 hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, 0, -1);
149 used = lstrlenA(buffer);
150 ok( (hr == S_OK) &&
151 ((used == INTERNET_MAX_URL_LENGTH - 1) || broken(used == 0)) ,
152 "got 0x%x and %d (expected S_OK and INTERNET_MAX_URL_LENGTH - 1)\n",
153 hr, used);
154
155 /* still succeed without a buffer for the result */
156 hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, NULL, 0, -1);
157 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
158
159 /* still succeed, when a length is given without a buffer */
160 hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, NULL, INTERNET_MAX_URL_LENGTH, -1);
161 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
162
163 /* this value does not exist */
164 memset(buffer, '#', sizeof(buffer)-1);
165 buffer[sizeof(buffer)-1] = '\0';
166 hr = pURLSubRegQueryA(regpath_iemain, does_not_exist, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
167 /* random bytes are copied to the buffer */
168 ok((hr == E_FAIL), "got 0x%x (expected E_FAIL)\n", hr);
169
170 /* the third parameter is ignored. Is it really a type? (data is REG_SZ) */
171 memset(buffer, '#', sizeof(buffer)-1);
172 buffer[sizeof(buffer)-1] = '\0';
173 hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_DWORD, buffer, INTERNET_MAX_URL_LENGTH, -1);
174 used = lstrlenA(buffer);
175 ok((hr == S_OK) && (used == len),
176 "got 0x%x and %d (expected S_OK and %d)\n", hr, used, len);
177
178 /* the function works for HKCU and HKLM */
179 memset(buffer, '#', sizeof(buffer)-1);
180 buffer[sizeof(buffer)-1] = '\0';
181 hr = pURLSubRegQueryA(regpath_shellfolders, appdata, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
182 used = lstrlenA(buffer);
183 ok(hr == S_OK, "got 0x%x and %d (expected S_OK)\n", hr, used);
184
185 memset(buffer, '#', sizeof(buffer)-1);
186 buffer[sizeof(buffer)-1] = '\0';
187 hr = pURLSubRegQueryA(regpath_shellfolders, common_appdata, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
188 used = lstrlenA(buffer);
189 ok(hr == S_OK, "got 0x%x and %d (expected S_OK)\n", hr, used);
190
191 /* todo: what does the last parameter mean? */
192 }
193
194 /* ################ */
195
196 static void test_ParseURLFromOutsideSourceA(void)
197 {
198 CHAR buffer[INTERNET_MAX_URL_LENGTH];
199 DWORD dummy;
200 DWORD maxlen;
201 DWORD len;
202 DWORD res;
203 int i;
204
205 if (!pParseURLFromOutsideSourceA) {
206 skip("ParseURLFromOutsideSourceA not found\n");
207 return;
208 }
209
210 for(i = 0; i < sizeof(ParseURL_table)/sizeof(ParseURL_table[0]); i++) {
211 memset(buffer, '#', sizeof(buffer)-1);
212 buffer[sizeof(buffer)-1] = '\0';
213 len = sizeof(buffer);
214 dummy = 0;
215 /* on success, string size including terminating 0 is returned for ansi version */
216 res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, &dummy);
217 /* len does not include the terminating 0, when buffer is large enough */
218 ok( res == (ParseURL_table[i].len+1) && len == ParseURL_table[i].len &&
219 !lstrcmpA(buffer, ParseURL_table[i].newurl),
220 "#%d: got %d and %d with '%s' (expected %d and %d with '%s')\n",
221 i, res, len, buffer, ParseURL_table[i].len+1, ParseURL_table[i].len, ParseURL_table[i].newurl);
222
223
224 /* use the size test only for the first examples */
225 if (i > 4) continue;
226
227 maxlen = len;
228
229 memset(buffer, '#', sizeof(buffer)-1);
230 buffer[sizeof(buffer)-1] = '\0';
231 len = maxlen + 1;
232 dummy = 0;
233 res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, &dummy);
234 ok( res != 0 && len == ParseURL_table[i].len &&
235 !lstrcmpA(buffer, ParseURL_table[i].newurl),
236 "#%d (+1): got %d and %d with '%s' (expected '!=0' and %d with '%s')\n",
237 i, res, len, buffer, ParseURL_table[i].len, ParseURL_table[i].newurl);
238
239 memset(buffer, '#', sizeof(buffer)-1);
240 buffer[sizeof(buffer)-1] = '\0';
241 len = maxlen;
242 dummy = 0;
243 res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, &dummy);
244 /* len includes the terminating 0, when the buffer is too small */
245 ok( res == 0 && len == ParseURL_table[i].len + 1,
246 "#%d (==): got %d and %d (expected '0' and %d)\n",
247 i, res, len, ParseURL_table[i].len + 1);
248
249 memset(buffer, '#', sizeof(buffer)-1);
250 buffer[sizeof(buffer)-1] = '\0';
251 len = maxlen-1;
252 dummy = 0;
253 res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, &dummy);
254 /* len includes the terminating 0 on XP SP1 and before, when the buffer is too small */
255 ok( res == 0 && (len == ParseURL_table[i].len || len == ParseURL_table[i].len + 1),
256 "#%d (-1): got %d and %d (expected '0' and %d or %d)\n",
257 i, res, len, ParseURL_table[i].len, ParseURL_table[i].len + 1);
258
259 memset(buffer, '#', sizeof(buffer)-1);
260 buffer[sizeof(buffer)-1] = '\0';
261 len = maxlen+1;
262 dummy = 0;
263 res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, NULL, &len, &dummy);
264 /* len does not include the terminating 0, when buffer is NULL */
265 ok( res == 0 && len == ParseURL_table[i].len,
266 "#%d (buffer): got %d and %d (expected '0' and %d)\n",
267 i, res, len, ParseURL_table[i].len);
268
269 if (0) {
270 /* that test crash on native shdocvw */
271 pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, NULL, &dummy);
272 }
273
274 memset(buffer, '#', sizeof(buffer)-1);
275 buffer[sizeof(buffer)-1] = '\0';
276 len = maxlen+1;
277 dummy = 0;
278 res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, NULL);
279 ok( res != 0 && len == ParseURL_table[i].len &&
280 !lstrcmpA(buffer, ParseURL_table[i].newurl),
281 "#%d (unknown): got %d and %d with '%s' (expected '!=0' and %d with '%s')\n",
282 i, res, len, buffer, ParseURL_table[i].len, ParseURL_table[i].newurl);
283 }
284 }
285
286 /* ################ */
287
288 static void test_ParseURLFromOutsideSourceW(void)
289 {
290 WCHAR urlW[INTERNET_MAX_URL_LENGTH];
291 WCHAR bufferW[INTERNET_MAX_URL_LENGTH];
292 CHAR bufferA[INTERNET_MAX_URL_LENGTH];
293 DWORD maxlen;
294 DWORD dummy;
295 DWORD len;
296 DWORD res;
297
298 if (!pParseURLFromOutsideSourceW) {
299 skip("ParseURLFromOutsideSourceW not found\n");
300 return;
301 }
302 MultiByteToWideChar(CP_ACP, 0, ParseURL_table[0].url, -1, urlW, INTERNET_MAX_URL_LENGTH);
303
304 memset(bufferA, '#', sizeof(bufferA)-1);
305 bufferA[sizeof(bufferA) - 1] = '\0';
306 MultiByteToWideChar(CP_ACP, 0, bufferA, -1, bufferW, INTERNET_MAX_URL_LENGTH);
307
308 /* len is in characters */
309 len = sizeof(bufferW)/sizeof(bufferW[0]);
310 dummy = 0;
311 /* on success, 1 is returned for unicode version */
312 res = pParseURLFromOutsideSourceW(urlW, bufferW, &len, &dummy);
313 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, bufferA, sizeof(bufferA), NULL, NULL);
314 ok( res == 1 && len == ParseURL_table[0].len &&
315 !lstrcmpA(bufferA, ParseURL_table[0].newurl),
316 "got %d and %d with '%s' (expected 1 and %d with '%s')\n",
317 res, len, bufferA, ParseURL_table[0].len, ParseURL_table[0].newurl);
318
319
320 maxlen = len;
321
322 memset(bufferA, '#', sizeof(bufferA)-1);
323 bufferA[sizeof(bufferA) - 1] = '\0';
324 MultiByteToWideChar(CP_ACP, 0, bufferA, -1, bufferW, INTERNET_MAX_URL_LENGTH);
325 len = maxlen+1;
326 dummy = 0;
327 res = pParseURLFromOutsideSourceW(urlW, bufferW, &len, &dummy);
328 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, bufferA, sizeof(bufferA), NULL, NULL);
329 /* len does not include the terminating 0, when buffer is large enough */
330 ok( res != 0 && len == ParseURL_table[0].len &&
331 !lstrcmpA(bufferA, ParseURL_table[0].newurl),
332 "+1: got %d and %d with '%s' (expected '!=0' and %d with '%s')\n",
333 res, len, bufferA, ParseURL_table[0].len, ParseURL_table[0].newurl);
334
335 len = maxlen;
336 dummy = 0;
337 res = pParseURLFromOutsideSourceW(urlW, bufferW, &len, &dummy);
338 /* len includes the terminating 0, when the buffer is too small */
339 ok( res == 0 && len == ParseURL_table[0].len + 1,
340 "==: got %d and %d (expected '0' and %d)\n",
341 res, len, ParseURL_table[0].len + 1);
342
343 len = maxlen - 1;
344 dummy = 0;
345 res = pParseURLFromOutsideSourceW(urlW, bufferW, &len, &dummy);
346 /* len includes the terminating 0 on XP SP1 and before, when the buffer is too small */
347 ok( res == 0 && (len == ParseURL_table[0].len || len == ParseURL_table[0].len + 1),
348 "-1: got %d and %d (expected '0' and %d or %d)\n",
349 res, len, ParseURL_table[0].len, ParseURL_table[0].len + 1);
350
351 }
352
353 /* ################ */
354
355 START_TEST(shdocvw)
356 {
357 init_functions();
358 test_URLSubRegQueryA();
359 test_ParseURLFromOutsideSourceA();
360 test_ParseURLFromOutsideSourceW();
361 FreeLibrary(hshdocvw);
362 }