wininet/tests: Fix compilation on systems that don't support nameless unions.
[wine.git] / dlls / wininet / tests / urlcache.c
blob5c12a81a4bdf656c08a3d8e187c5daecc1364d50
1 /*
2 * URL Cache Tests
4 * Copyright 2008 Robert Shearman for CodeWeavers
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.
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.
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
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wininet.h"
28 #include "winineti.h"
30 #include "wine/test.h"
32 #define TEST_URL "http://urlcachetest.winehq.org/index.html"
33 #define TEST_URL1 "Visited: user@http://urlcachetest.winehq.org/index.html"
35 static BOOL (WINAPI *pDeleteUrlCacheEntryA)(LPCSTR);
36 static BOOL (WINAPI *pUnlockUrlCacheEntryFileA)(LPCSTR,DWORD);
38 static char filenameA[MAX_PATH + 1];
39 static char filenameA1[MAX_PATH + 1];
41 static void check_cache_entry_infoA(const char *returnedfrom, LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo)
43 ok(lpCacheEntryInfo->dwStructSize == sizeof(*lpCacheEntryInfo), "%s: dwStructSize was %d\n", returnedfrom, lpCacheEntryInfo->dwStructSize);
44 ok(!strcmp(lpCacheEntryInfo->lpszSourceUrlName, TEST_URL), "%s: lpszSourceUrlName should be %s instead of %s\n", returnedfrom, TEST_URL, lpCacheEntryInfo->lpszSourceUrlName);
45 ok(!strcmp(lpCacheEntryInfo->lpszLocalFileName, filenameA), "%s: lpszLocalFileName should be %s instead of %s\n", returnedfrom, filenameA, lpCacheEntryInfo->lpszLocalFileName);
46 ok(!strcmp(lpCacheEntryInfo->lpszFileExtension, "html"), "%s: lpszFileExtension should be html instead of %s\n", returnedfrom, lpCacheEntryInfo->lpszFileExtension);
49 static void test_find_url_cache_entriesA(void)
51 BOOL ret;
52 HANDLE hEnumHandle;
53 BOOL found = FALSE;
54 DWORD cbCacheEntryInfo;
55 DWORD cbCacheEntryInfoSaved;
56 LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo;
58 cbCacheEntryInfo = 0;
59 SetLastError(0xdeadbeef);
60 hEnumHandle = FindFirstUrlCacheEntry(NULL, NULL, &cbCacheEntryInfo);
61 ok(!hEnumHandle, "FindFirstUrlCacheEntry should have failed\n");
62 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "FindFirstUrlCacheEntry should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
63 lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo * sizeof(char));
64 cbCacheEntryInfoSaved = cbCacheEntryInfo;
65 hEnumHandle = FindFirstUrlCacheEntry(NULL, lpCacheEntryInfo, &cbCacheEntryInfo);
66 ok(hEnumHandle != NULL, "FindFirstUrlCacheEntry failed with error %d\n", GetLastError());
67 while (TRUE)
69 if (!strcmp(lpCacheEntryInfo->lpszSourceUrlName, TEST_URL))
71 found = TRUE;
72 break;
74 SetLastError(0xdeadbeef);
75 cbCacheEntryInfo = cbCacheEntryInfoSaved;
76 ret = FindNextUrlCacheEntry(hEnumHandle, lpCacheEntryInfo, &cbCacheEntryInfo);
77 if (!ret)
79 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
81 lpCacheEntryInfo = HeapReAlloc(GetProcessHeap(), 0, lpCacheEntryInfo, cbCacheEntryInfo);
82 cbCacheEntryInfoSaved = cbCacheEntryInfo;
83 ret = FindNextUrlCacheEntry(hEnumHandle, lpCacheEntryInfo, &cbCacheEntryInfo);
86 ok(ret, "FindNextUrlCacheEntry failed with error %d\n", GetLastError());
87 if (!ret)
88 break;
90 ok(found, "committed url cache entry not found during enumeration\n");
92 ret = FindCloseUrlCache(hEnumHandle);
93 ok(ret, "FindCloseUrlCache failed with error %d\n", GetLastError());
96 static void test_GetUrlCacheEntryInfoExA(void)
98 BOOL ret;
99 DWORD cbCacheEntryInfo, cbRedirectUrl;
100 LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo;
102 SetLastError(0xdeadbeef);
103 ret = GetUrlCacheEntryInfoEx(NULL, NULL, NULL, NULL, NULL, NULL, 0);
104 ok(!ret, "GetUrlCacheEntryInfoEx with NULL URL and NULL args should have failed\n");
105 ok(GetLastError() == ERROR_INVALID_PARAMETER,
106 "GetUrlCacheEntryInfoEx with NULL URL and NULL args should have set last error to ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
108 cbCacheEntryInfo = sizeof(INTERNET_CACHE_ENTRY_INFO);
109 SetLastError(0xdeadbeef);
110 ret = GetUrlCacheEntryInfoEx("", NULL, &cbCacheEntryInfo, NULL, NULL, NULL, 0);
111 ok(!ret, "GetUrlCacheEntryInfoEx with zero-length buffer should fail\n");
112 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
113 "GetUrlCacheEntryInfoEx should have set last error to ERROR_FILE_NOT_FOUND instead of %d\n", GetLastError());
115 ret = GetUrlCacheEntryInfoEx(TEST_URL, NULL, NULL, NULL, NULL, NULL, 0);
116 ok(ret, "GetUrlCacheEntryInfoEx with NULL args failed with error %d\n", GetLastError());
118 cbCacheEntryInfo = 0;
119 SetLastError(0xdeadbeef);
120 ret = GetUrlCacheEntryInfoEx(TEST_URL, NULL, &cbCacheEntryInfo, NULL, NULL, NULL, 0);
121 ok(!ret, "GetUrlCacheEntryInfoEx with zero-length buffer should fail\n");
122 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
123 "GetUrlCacheEntryInfoEx should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
125 lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
127 SetLastError(0xdeadbeef);
128 ret = GetUrlCacheEntryInfoEx(TEST_URL, lpCacheEntryInfo, &cbCacheEntryInfo, NULL, NULL, NULL, 0x200);
129 ok(!ret, "GetUrlCacheEntryInfoEx succeeded\n");
130 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
131 "GetUrlCacheEntryInfoEx should have set last error to ERROR_FILE_NOT_FOUND instead of %d\n", GetLastError());
133 ret = GetUrlCacheEntryInfoEx(TEST_URL, lpCacheEntryInfo, &cbCacheEntryInfo, NULL, NULL, NULL, 0);
134 ok(ret, "GetUrlCacheEntryInfoEx failed with error %d\n", GetLastError());
136 check_cache_entry_infoA("GetUrlCacheEntryInfoEx", lpCacheEntryInfo);
138 cbCacheEntryInfo = 100000;
139 SetLastError(0xdeadbeef);
140 ret = GetUrlCacheEntryInfoEx(TEST_URL, NULL, &cbCacheEntryInfo, NULL, NULL, NULL, 0);
141 ok(!ret, "GetUrlCacheEntryInfoEx with zero-length buffer should fail\n");
142 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetUrlCacheEntryInfoEx should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
144 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
146 /* Querying the redirect URL fails with ERROR_INVALID_PARAMETER */
147 SetLastError(0xdeadbeef);
148 ret = GetUrlCacheEntryInfoEx(TEST_URL, NULL, NULL, NULL, &cbRedirectUrl, NULL, 0);
149 ok(GetLastError() == ERROR_INVALID_PARAMETER,
150 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
151 SetLastError(0xdeadbeef);
152 ret = GetUrlCacheEntryInfoEx(TEST_URL, NULL, &cbCacheEntryInfo, NULL, &cbRedirectUrl, NULL, 0);
153 ok(GetLastError() == ERROR_INVALID_PARAMETER,
154 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
157 static void test_RetrieveUrlCacheEntryA(void)
159 BOOL ret;
160 DWORD cbCacheEntryInfo;
162 cbCacheEntryInfo = 0;
163 SetLastError(0xdeadbeef);
164 ret = RetrieveUrlCacheEntryFile(NULL, NULL, &cbCacheEntryInfo, 0);
165 ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
166 ok(GetLastError() == ERROR_INVALID_PARAMETER, "RetrieveUrlCacheEntryFile should have set last error to ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
168 if (0)
170 /* Crashes on Win9x, NT4 and W2K */
171 SetLastError(0xdeadbeef);
172 ret = RetrieveUrlCacheEntryFile(TEST_URL, NULL, NULL, 0);
173 ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
174 ok(GetLastError() == ERROR_INVALID_PARAMETER, "RetrieveUrlCacheEntryFile should have set last error to ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
177 SetLastError(0xdeadbeef);
178 cbCacheEntryInfo = 100000;
179 ret = RetrieveUrlCacheEntryFile(NULL, NULL, &cbCacheEntryInfo, 0);
180 ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
181 ok(GetLastError() == ERROR_INVALID_PARAMETER, "RetrieveUrlCacheEntryFile should have set last error to ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
184 static void test_IsUrlCacheEntryExpiredA(void)
186 static const char uncached_url[] =
187 "What's the airspeed velocity of an unladen swallow?";
188 BOOL ret;
189 FILETIME ft;
190 DWORD size;
191 LPINTERNET_CACHE_ENTRY_INFO info;
192 ULARGE_INTEGER exp_time;
194 /* The function returns TRUE when the output time is NULL or the tested URL
195 * is NULL.
197 ret = IsUrlCacheEntryExpiredA(NULL, 0, NULL);
198 ok(ret, "expected TRUE\n");
199 ft.dwLowDateTime = 0xdeadbeef;
200 ft.dwHighDateTime = 0xbaadf00d;
201 ret = IsUrlCacheEntryExpiredA(NULL, 0, &ft);
202 ok(ret, "expected TRUE\n");
203 ok(ft.dwLowDateTime == 0xdeadbeef && ft.dwHighDateTime == 0xbaadf00d,
204 "expected time to be unchanged, got (%u,%u)\n",
205 ft.dwLowDateTime, ft.dwHighDateTime);
206 ret = IsUrlCacheEntryExpiredA(TEST_URL, 0, NULL);
207 ok(ret, "expected TRUE\n");
209 /* The return value should indicate whether the URL is expired,
210 * and the filetime indicates the last modified time, but a cache entry
211 * with a zero expire time is "not expired".
213 ft.dwLowDateTime = 0xdeadbeef;
214 ft.dwHighDateTime = 0xbaadf00d;
215 ret = IsUrlCacheEntryExpiredA(TEST_URL, 0, &ft);
216 ok(!ret, "expected FALSE\n");
217 ok(!ft.dwLowDateTime && !ft.dwHighDateTime,
218 "expected time (0,0), got (%u,%u)\n",
219 ft.dwLowDateTime, ft.dwHighDateTime);
221 /* Same behavior with bogus flags. */
222 ft.dwLowDateTime = 0xdeadbeef;
223 ft.dwHighDateTime = 0xbaadf00d;
224 ret = IsUrlCacheEntryExpiredA(TEST_URL, 0xffffffff, &ft);
225 ok(!ret, "expected FALSE\n");
226 ok(!ft.dwLowDateTime && !ft.dwHighDateTime,
227 "expected time (0,0), got (%u,%u)\n",
228 ft.dwLowDateTime, ft.dwHighDateTime);
230 /* Set the expire time to a point in the past.. */
231 ret = GetUrlCacheEntryInfo(TEST_URL, NULL, &size);
232 ok(!ret, "GetUrlCacheEntryInfo should have failed\n");
233 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
234 "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
235 info = HeapAlloc(GetProcessHeap(), 0, size);
236 ret = GetUrlCacheEntryInfo(TEST_URL, info, &size);
237 GetSystemTimeAsFileTime(&info->ExpireTime);
238 exp_time.u.LowPart = info->ExpireTime.dwLowDateTime;
239 exp_time.u.HighPart = info->ExpireTime.dwHighDateTime;
240 exp_time.QuadPart -= 10 * 60 * (ULONGLONG)10000000;
241 info->ExpireTime.dwLowDateTime = exp_time.u.LowPart;
242 info->ExpireTime.dwHighDateTime = exp_time.u.HighPart;
243 ret = SetUrlCacheEntryInfo(TEST_URL, info, CACHE_ENTRY_EXPTIME_FC);
244 ok(ret, "SetUrlCacheEntryInfo failed: %d\n", GetLastError());
245 ft.dwLowDateTime = 0xdeadbeef;
246 ft.dwHighDateTime = 0xbaadf00d;
247 /* and the entry should be expired. */
248 ret = IsUrlCacheEntryExpiredA(TEST_URL, 0, &ft);
249 ok(ret, "expected TRUE\n");
250 /* The modified time returned is 0. */
251 ok(!ft.dwLowDateTime && !ft.dwHighDateTime,
252 "expected time (0,0), got (%u,%u)\n",
253 ft.dwLowDateTime, ft.dwHighDateTime);
254 /* Set the expire time to a point in the future.. */
255 exp_time.QuadPart += 20 * 60 * (ULONGLONG)10000000;
256 info->ExpireTime.dwLowDateTime = exp_time.u.LowPart;
257 info->ExpireTime.dwHighDateTime = exp_time.u.HighPart;
258 ret = SetUrlCacheEntryInfo(TEST_URL, info, CACHE_ENTRY_EXPTIME_FC);
259 ok(ret, "SetUrlCacheEntryInfo failed: %d\n", GetLastError());
260 ft.dwLowDateTime = 0xdeadbeef;
261 ft.dwHighDateTime = 0xbaadf00d;
262 /* and the entry should no longer be expired. */
263 ret = IsUrlCacheEntryExpiredA(TEST_URL, 0, &ft);
264 ok(!ret, "expected FALSE\n");
265 /* The modified time returned is still 0. */
266 ok(!ft.dwLowDateTime && !ft.dwHighDateTime,
267 "expected time (0,0), got (%u,%u)\n",
268 ft.dwLowDateTime, ft.dwHighDateTime);
269 /* Set the modified time... */
270 GetSystemTimeAsFileTime(&info->LastModifiedTime);
271 ret = SetUrlCacheEntryInfo(TEST_URL, info, CACHE_ENTRY_MODTIME_FC);
272 ok(ret, "SetUrlCacheEntryInfo failed: %d\n", GetLastError());
273 /* and the entry should still be unexpired.. */
274 ret = IsUrlCacheEntryExpiredA(TEST_URL, 0, &ft);
275 ok(!ret, "expected FALSE\n");
276 /* but the modified time returned is the last modified time just set. */
277 ok(ft.dwLowDateTime == info->LastModifiedTime.dwLowDateTime &&
278 ft.dwHighDateTime == info->LastModifiedTime.dwHighDateTime,
279 "expected time (%u,%u), got (%u,%u)\n",
280 info->LastModifiedTime.dwLowDateTime,
281 info->LastModifiedTime.dwHighDateTime,
282 ft.dwLowDateTime, ft.dwHighDateTime);
283 HeapFree(GetProcessHeap(), 0, info);
285 /* An uncached URL is implicitly expired, but with unknown time. */
286 ft.dwLowDateTime = 0xdeadbeef;
287 ft.dwHighDateTime = 0xbaadf00d;
288 ret = IsUrlCacheEntryExpiredA(uncached_url, 0, &ft);
289 ok(ret, "expected TRUE\n");
290 ok(!ft.dwLowDateTime && !ft.dwHighDateTime,
291 "expected time (0,0), got (%u,%u)\n",
292 ft.dwLowDateTime, ft.dwHighDateTime);
295 static void _check_file_exists(LONG l, LPCSTR filename)
297 HANDLE file;
299 file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
300 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
301 ok_(__FILE__,l)(file != INVALID_HANDLE_VALUE,
302 "expected file to exist, CreateFile failed with error %d\n",
303 GetLastError());
304 CloseHandle(file);
307 #define check_file_exists(f) _check_file_exists(__LINE__, f)
309 static void _check_file_not_exists(LONG l, LPCSTR filename)
311 HANDLE file;
313 file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
314 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
315 ok_(__FILE__,l)(file == INVALID_HANDLE_VALUE,
316 "expected file not to exist\n");
317 if (file != INVALID_HANDLE_VALUE)
318 CloseHandle(file);
321 #define check_file_not_exists(f) _check_file_not_exists(__LINE__, f)
323 static void create_and_write_file(LPCSTR filename, void *data, DWORD len)
325 HANDLE file;
326 DWORD written;
327 BOOL ret;
329 file = CreateFileA(filename, GENERIC_WRITE,
330 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
331 FILE_ATTRIBUTE_NORMAL, NULL);
332 ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed with error %d\n", GetLastError());
334 ret = WriteFile(file, data, len, &written, NULL);
335 ok(ret, "WriteFile failed with error %d\n", GetLastError());
337 CloseHandle(file);
340 static void test_urlcacheA(void)
342 static char ok_header[] = "HTTP/1.0 200 OK\r\n\r\n";
343 BOOL ret;
344 HANDLE hFile;
345 BYTE zero_byte = 0;
346 LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo;
347 DWORD cbCacheEntryInfo;
348 static const FILETIME filetime_zero;
349 FILETIME now;
351 ret = CreateUrlCacheEntry(TEST_URL, 0, "html", filenameA, 0);
352 ok(ret, "CreateUrlCacheEntry failed with error %d\n", GetLastError());
354 ret = CreateUrlCacheEntry(TEST_URL, 0, "html", filenameA1, 0);
355 ok(ret, "CreateUrlCacheEntry failed with error %d\n", GetLastError());
357 ok(lstrcmpiA(filenameA, filenameA1), "expected a different file name\n");
359 create_and_write_file(filenameA, &zero_byte, sizeof(zero_byte));
361 ret = CommitUrlCacheEntry(TEST_URL1, NULL, filetime_zero, filetime_zero, NORMAL_CACHE_ENTRY|URLHISTORY_CACHE_ENTRY, NULL, 0, NULL, NULL);
362 ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
363 cbCacheEntryInfo = 0;
364 ret = GetUrlCacheEntryInfo(TEST_URL1, NULL, &cbCacheEntryInfo);
365 ok(!ret, "GetUrlCacheEntryInfo should have failed\n");
366 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
367 "GetUrlCacheEntryInfo should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
368 lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
369 ret = GetUrlCacheEntryInfo(TEST_URL1, lpCacheEntryInfo, &cbCacheEntryInfo);
370 ok(ret, "GetUrlCacheEntryInfo failed with error %d\n", GetLastError());
371 ok(!memcmp(&lpCacheEntryInfo->ExpireTime, &filetime_zero, sizeof(FILETIME)),
372 "expected zero ExpireTime\n");
373 ok(!memcmp(&lpCacheEntryInfo->LastModifiedTime, &filetime_zero, sizeof(FILETIME)),
374 "expected zero LastModifiedTime\n");
375 ok(lpCacheEntryInfo->CacheEntryType == (NORMAL_CACHE_ENTRY|URLHISTORY_CACHE_ENTRY) ||
376 broken(lpCacheEntryInfo->CacheEntryType == NORMAL_CACHE_ENTRY /* NT4/W2k */),
377 "expected type NORMAL_CACHE_ENTRY|URLHISTORY_CACHE_ENTRY, got %08x\n",
378 lpCacheEntryInfo->CacheEntryType);
379 ok(!U(*lpCacheEntryInfo).dwExemptDelta, "expected dwExemptDelta 0, got %d\n",
380 U(*lpCacheEntryInfo).dwExemptDelta);
381 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
383 /* A subsequent commit with a different time/type doesn't change the type */
384 GetSystemTimeAsFileTime(&now);
385 ret = CommitUrlCacheEntry(TEST_URL1, NULL, now, now, NORMAL_CACHE_ENTRY,
386 (LPBYTE)ok_header, strlen(ok_header), NULL, NULL);
387 ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
388 cbCacheEntryInfo = 0;
389 ret = GetUrlCacheEntryInfo(TEST_URL1, NULL, &cbCacheEntryInfo);
390 ok(!ret, "GetUrlCacheEntryInfo should have failed\n");
391 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
392 "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
393 lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
394 ret = GetUrlCacheEntryInfo(TEST_URL1, lpCacheEntryInfo, &cbCacheEntryInfo);
395 ok(ret, "GetUrlCacheEntryInfo failed with error %d\n", GetLastError());
396 /* but it does change the time.. */
397 todo_wine
398 ok(memcmp(&lpCacheEntryInfo->ExpireTime, &filetime_zero, sizeof(FILETIME)),
399 "expected positive ExpireTime\n");
400 todo_wine
401 ok(memcmp(&lpCacheEntryInfo->LastModifiedTime, &filetime_zero, sizeof(FILETIME)),
402 "expected positive LastModifiedTime\n");
403 ok(lpCacheEntryInfo->CacheEntryType == (NORMAL_CACHE_ENTRY|URLHISTORY_CACHE_ENTRY) ||
404 broken(lpCacheEntryInfo->CacheEntryType == NORMAL_CACHE_ENTRY /* NT4/W2k */),
405 "expected type NORMAL_CACHE_ENTRY|URLHISTORY_CACHE_ENTRY, got %08x\n",
406 lpCacheEntryInfo->CacheEntryType);
407 /* and set the headers. */
408 todo_wine
409 ok(lpCacheEntryInfo->dwHeaderInfoSize == 19,
410 "expected headers size 19, got %d\n",
411 lpCacheEntryInfo->dwHeaderInfoSize);
412 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
414 ret = CommitUrlCacheEntry(TEST_URL, filenameA, filetime_zero, filetime_zero, NORMAL_CACHE_ENTRY, NULL, 0, "html", NULL);
415 ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
417 cbCacheEntryInfo = 0;
418 SetLastError(0xdeadbeef);
419 ret = RetrieveUrlCacheEntryFile(TEST_URL, NULL, &cbCacheEntryInfo, 0);
420 ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
421 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
422 "RetrieveUrlCacheEntryFile should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
424 lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
425 ret = RetrieveUrlCacheEntryFile(TEST_URL, lpCacheEntryInfo, &cbCacheEntryInfo, 0);
426 ok(ret, "RetrieveUrlCacheEntryFile failed with error %d\n", GetLastError());
428 check_cache_entry_infoA("RetrieveUrlCacheEntryFile", lpCacheEntryInfo);
430 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
432 cbCacheEntryInfo = 0;
433 SetLastError(0xdeadbeef);
434 ret = RetrieveUrlCacheEntryFile(TEST_URL1, NULL, &cbCacheEntryInfo, 0);
435 ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
436 ok(GetLastError() == ERROR_INVALID_DATA,
437 "RetrieveUrlCacheEntryFile should have set last error to ERROR_INVALID_DATA instead of %d\n", GetLastError());
439 if (pUnlockUrlCacheEntryFileA)
441 ret = pUnlockUrlCacheEntryFileA(TEST_URL, 0);
442 ok(ret, "UnlockUrlCacheEntryFileA failed with error %d\n", GetLastError());
445 /* test Find*UrlCacheEntry functions */
446 test_find_url_cache_entriesA();
448 test_GetUrlCacheEntryInfoExA();
449 test_RetrieveUrlCacheEntryA();
450 test_IsUrlCacheEntryExpiredA();
452 if (pDeleteUrlCacheEntryA)
454 ret = pDeleteUrlCacheEntryA(TEST_URL);
455 ok(ret, "DeleteUrlCacheEntryA failed with error %d\n", GetLastError());
456 ret = pDeleteUrlCacheEntryA(TEST_URL1);
457 ok(ret, "DeleteUrlCacheEntryA failed with error %d\n", GetLastError());
460 SetLastError(0xdeadbeef);
461 ret = DeleteFile(filenameA);
462 todo_wine
463 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "local file should no longer exist\n");
465 /* Creating two entries with the same URL */
466 ret = CreateUrlCacheEntry(TEST_URL, 0, "html", filenameA, 0);
467 ok(ret, "CreateUrlCacheEntry failed with error %d\n", GetLastError());
469 ret = CreateUrlCacheEntry(TEST_URL, 0, "html", filenameA1, 0);
470 ok(ret, "CreateUrlCacheEntry failed with error %d\n", GetLastError());
472 ok(lstrcmpiA(filenameA, filenameA1), "expected a different file name\n");
474 create_and_write_file(filenameA, &zero_byte, sizeof(zero_byte));
475 create_and_write_file(filenameA1, &zero_byte, sizeof(zero_byte));
476 check_file_exists(filenameA);
477 check_file_exists(filenameA1);
479 ret = CommitUrlCacheEntry(TEST_URL, filenameA, filetime_zero,
480 filetime_zero, NORMAL_CACHE_ENTRY, (LPBYTE)ok_header,
481 strlen(ok_header), "html", NULL);
482 ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
483 check_file_exists(filenameA);
484 check_file_exists(filenameA1);
485 ret = CommitUrlCacheEntry(TEST_URL, filenameA1, filetime_zero,
486 filetime_zero, COOKIE_CACHE_ENTRY, NULL, 0, "html", NULL);
487 ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
488 /* By committing the same URL a second time, the prior entry is
489 * overwritten...
491 cbCacheEntryInfo = 0;
492 SetLastError(0xdeadbeef);
493 ret = GetUrlCacheEntryInfo(TEST_URL, NULL, &cbCacheEntryInfo);
494 ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
495 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
496 "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
497 lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
498 ret = GetUrlCacheEntryInfo(TEST_URL, lpCacheEntryInfo, &cbCacheEntryInfo);
499 ok(ret, "GetUrlCacheEntryInfo failed with error %d\n", GetLastError());
500 /* with the previous entry type retained.. */
501 ok(lpCacheEntryInfo->CacheEntryType & NORMAL_CACHE_ENTRY,
502 "expected cache entry type NORMAL_CACHE_ENTRY, got %d (0x%08x)\n",
503 lpCacheEntryInfo->CacheEntryType, lpCacheEntryInfo->CacheEntryType);
504 /* and the headers overwritten.. */
505 todo_wine
506 ok(!lpCacheEntryInfo->dwHeaderInfoSize, "expected headers size 0, got %d\n",
507 lpCacheEntryInfo->dwHeaderInfoSize);
508 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
509 /* and the previous filename shouldn't exist. */
510 todo_wine
511 check_file_not_exists(filenameA);
512 check_file_exists(filenameA1);
514 if (pDeleteUrlCacheEntryA)
516 ret = pDeleteUrlCacheEntryA(TEST_URL);
517 ok(ret, "DeleteUrlCacheEntryA failed with error %d\n", GetLastError());
518 todo_wine
519 check_file_not_exists(filenameA);
520 todo_wine
521 check_file_not_exists(filenameA1);
522 /* Just in case, clean up files */
523 DeleteFileA(filenameA1);
524 DeleteFileA(filenameA);
527 /* Check whether a retrieved cache entry can be deleted before it's
528 * unlocked:
530 ret = CreateUrlCacheEntry(TEST_URL, 0, "html", filenameA, 0);
531 ok(ret, "CreateUrlCacheEntry failed with error %d\n", GetLastError());
532 ret = CommitUrlCacheEntry(TEST_URL, filenameA, filetime_zero, filetime_zero,
533 NORMAL_CACHE_ENTRY, NULL, 0, "html", NULL);
534 ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
536 cbCacheEntryInfo = 0;
537 SetLastError(0xdeadbeef);
538 ret = RetrieveUrlCacheEntryFile(TEST_URL, NULL, &cbCacheEntryInfo, 0);
539 ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
540 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
541 "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
543 lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
544 ret = RetrieveUrlCacheEntryFile(TEST_URL, lpCacheEntryInfo,
545 &cbCacheEntryInfo, 0);
546 ok(ret, "RetrieveUrlCacheEntryFile failed with error %d\n", GetLastError());
548 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
550 if (pDeleteUrlCacheEntryA)
552 ret = pDeleteUrlCacheEntryA(TEST_URL);
553 todo_wine
554 ok(!ret, "Expected failure\n");
555 todo_wine
556 ok(GetLastError() == ERROR_SHARING_VIOLATION,
557 "Expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
558 check_file_exists(filenameA);
560 if (pUnlockUrlCacheEntryFileA)
562 check_file_exists(filenameA);
563 ret = pUnlockUrlCacheEntryFileA(TEST_URL, 0);
564 todo_wine
565 ok(ret, "UnlockUrlCacheEntryFileA failed: %d\n", GetLastError());
566 /* By unlocking the already-deleted cache entry, the file associated
567 * with it is deleted..
569 todo_wine
570 check_file_not_exists(filenameA);
571 /* (just in case, delete file) */
572 DeleteFileA(filenameA);
574 if (pDeleteUrlCacheEntryA)
576 /* and a subsequent deletion should fail. */
577 ret = pDeleteUrlCacheEntryA(TEST_URL);
578 ok(!ret, "Expected failure\n");
579 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
580 "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
583 /* Test whether preventing a file from being deleted causes
584 * DeleteUrlCacheEntryA to fail.
586 ret = CreateUrlCacheEntry(TEST_URL, 0, "html", filenameA, 0);
587 ok(ret, "CreateUrlCacheEntry failed with error %d\n", GetLastError());
589 create_and_write_file(filenameA, &zero_byte, sizeof(zero_byte));
590 check_file_exists(filenameA);
592 ret = CommitUrlCacheEntry(TEST_URL, filenameA, filetime_zero,
593 filetime_zero, NORMAL_CACHE_ENTRY, (LPBYTE)ok_header,
594 strlen(ok_header), "html", NULL);
595 ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
596 check_file_exists(filenameA);
597 hFile = CreateFileA(filenameA, GENERIC_READ, 0, NULL, OPEN_EXISTING,
598 FILE_ATTRIBUTE_NORMAL, NULL);
599 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA failed: %d\n",
600 GetLastError());
601 if (pDeleteUrlCacheEntryA)
603 /* DeleteUrlCacheEntryA should succeed.. */
604 ret = pDeleteUrlCacheEntryA(TEST_URL);
605 ok(ret, "DeleteUrlCacheEntryA failed with error %d\n", GetLastError());
607 CloseHandle(hFile);
608 if (pDeleteUrlCacheEntryA)
610 /* and a subsequent deletion should fail.. */
611 ret = pDeleteUrlCacheEntryA(TEST_URL);
612 ok(!ret, "Expected failure\n");
613 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
614 "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
616 /* and the file should be untouched. */
617 check_file_exists(filenameA);
618 DeleteFileA(filenameA);
620 /* Try creating a sticky entry. Unlike non-sticky entries, the filename
621 * must have been set already.
623 SetLastError(0xdeadbeef);
624 ret = CommitUrlCacheEntry(TEST_URL, NULL, filetime_zero, filetime_zero,
625 STICKY_CACHE_ENTRY, (LPBYTE)ok_header, strlen(ok_header), "html",
626 NULL);
627 ok(!ret, "expected failure\n");
628 ok(GetLastError() == ERROR_INVALID_PARAMETER,
629 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
630 SetLastError(0xdeadbeef);
631 ret = CommitUrlCacheEntry(TEST_URL, NULL, filetime_zero, filetime_zero,
632 NORMAL_CACHE_ENTRY|STICKY_CACHE_ENTRY,
633 (LPBYTE)ok_header, strlen(ok_header), "html", NULL);
634 ok(!ret, "expected failure\n");
635 ok(GetLastError() == ERROR_INVALID_PARAMETER,
636 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
637 ret = CreateUrlCacheEntry(TEST_URL, 0, "html", filenameA, 0);
638 ok(ret, "CreateUrlCacheEntry failed with error %d\n", GetLastError());
639 create_and_write_file(filenameA, &zero_byte, sizeof(zero_byte));
640 ret = CommitUrlCacheEntry(TEST_URL, filenameA, filetime_zero, filetime_zero,
641 NORMAL_CACHE_ENTRY|STICKY_CACHE_ENTRY,
642 (LPBYTE)ok_header, strlen(ok_header), "html", NULL);
643 ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
644 cbCacheEntryInfo = 0;
645 SetLastError(0xdeadbeef);
646 ret = GetUrlCacheEntryInfo(TEST_URL, NULL, &cbCacheEntryInfo);
647 ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
648 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
649 "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
650 lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
651 ret = GetUrlCacheEntryInfo(TEST_URL, lpCacheEntryInfo, &cbCacheEntryInfo);
652 ok(ret, "GetUrlCacheEntryInfo failed with error %d\n", GetLastError());
653 ok(lpCacheEntryInfo->CacheEntryType & (NORMAL_CACHE_ENTRY|STICKY_CACHE_ENTRY),
654 "expected cache entry type NORMAL_CACHE_ENTRY | STICKY_CACHE_ENTRY, got %d (0x%08x)\n",
655 lpCacheEntryInfo->CacheEntryType, lpCacheEntryInfo->CacheEntryType);
656 ok(U(*lpCacheEntryInfo).dwExemptDelta == 86400,
657 "expected dwExemptDelta 864000, got %d\n",
658 U(*lpCacheEntryInfo).dwExemptDelta);
659 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
660 if (pDeleteUrlCacheEntryA)
662 ret = pDeleteUrlCacheEntryA(TEST_URL);
663 ok(ret, "DeleteUrlCacheEntryA failed with error %d\n", GetLastError());
664 /* When explicitly deleting the cache entry, the file is also deleted */
665 todo_wine
666 check_file_not_exists(filenameA);
668 /* Test once again, setting the exempt delta via SetUrlCacheEntryInfo */
669 ret = CreateUrlCacheEntry(TEST_URL, 0, "html", filenameA, 0);
670 ok(ret, "CreateUrlCacheEntry failed with error %d\n", GetLastError());
671 create_and_write_file(filenameA, &zero_byte, sizeof(zero_byte));
672 ret = CommitUrlCacheEntry(TEST_URL, filenameA, filetime_zero, filetime_zero,
673 NORMAL_CACHE_ENTRY|STICKY_CACHE_ENTRY,
674 (LPBYTE)ok_header, strlen(ok_header), "html", NULL);
675 ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
676 cbCacheEntryInfo = 0;
677 SetLastError(0xdeadbeef);
678 ret = GetUrlCacheEntryInfo(TEST_URL, NULL, &cbCacheEntryInfo);
679 ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
680 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
681 "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
682 lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
683 ret = GetUrlCacheEntryInfo(TEST_URL, lpCacheEntryInfo, &cbCacheEntryInfo);
684 ok(ret, "GetUrlCacheEntryInfo failed with error %d\n", GetLastError());
685 ok(lpCacheEntryInfo->CacheEntryType & (NORMAL_CACHE_ENTRY|STICKY_CACHE_ENTRY),
686 "expected cache entry type NORMAL_CACHE_ENTRY | STICKY_CACHE_ENTRY, got %d (0x%08x)\n",
687 lpCacheEntryInfo->CacheEntryType, lpCacheEntryInfo->CacheEntryType);
688 ok(U(*lpCacheEntryInfo).dwExemptDelta == 86400,
689 "expected dwExemptDelta 864000, got %d\n",
690 U(*lpCacheEntryInfo).dwExemptDelta);
691 U(*lpCacheEntryInfo).dwExemptDelta = 0;
692 ret = SetUrlCacheEntryInfoA(TEST_URL, lpCacheEntryInfo,
693 CACHE_ENTRY_EXEMPT_DELTA_FC);
694 ok(ret, "SetUrlCacheEntryInfo failed: %d\n", GetLastError());
695 ret = GetUrlCacheEntryInfo(TEST_URL, lpCacheEntryInfo, &cbCacheEntryInfo);
696 ok(ret, "GetUrlCacheEntryInfo failed with error %d\n", GetLastError());
697 ok(!U(*lpCacheEntryInfo).dwExemptDelta, "expected dwExemptDelta 0, got %d\n",
698 U(*lpCacheEntryInfo).dwExemptDelta);
699 /* See whether a sticky cache entry has the flag cleared once the exempt
700 * delta is meaningless.
702 ok(lpCacheEntryInfo->CacheEntryType & (NORMAL_CACHE_ENTRY|STICKY_CACHE_ENTRY),
703 "expected cache entry type NORMAL_CACHE_ENTRY | STICKY_CACHE_ENTRY, got %d (0x%08x)\n",
704 lpCacheEntryInfo->CacheEntryType, lpCacheEntryInfo->CacheEntryType);
705 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
706 if (pDeleteUrlCacheEntryA)
708 ret = pDeleteUrlCacheEntryA(TEST_URL);
709 ok(ret, "DeleteUrlCacheEntryA failed with error %d\n", GetLastError());
710 todo_wine
711 check_file_not_exists(filenameA);
715 static void test_FindCloseUrlCache(void)
717 BOOL r;
718 DWORD err;
720 SetLastError(0xdeadbeef);
721 r = FindCloseUrlCache(NULL);
722 err = GetLastError();
723 ok(0 == r, "expected 0, got %d\n", r);
724 ok(ERROR_INVALID_HANDLE == err, "expected %d, got %d\n", ERROR_INVALID_HANDLE, err);
727 static void test_GetDiskInfoA(void)
729 BOOL ret;
730 DWORD error, cluster_size;
731 DWORDLONG free, total;
732 char path[MAX_PATH], *p;
734 GetSystemDirectoryA(path, MAX_PATH);
735 if ((p = strchr(path, '\\'))) *++p = 0;
737 ret = GetDiskInfoA(path, &cluster_size, &free, &total);
738 ok(ret, "GetDiskInfoA failed %u\n", GetLastError());
740 ret = GetDiskInfoA(path, &cluster_size, &free, NULL);
741 ok(ret, "GetDiskInfoA failed %u\n", GetLastError());
743 ret = GetDiskInfoA(path, &cluster_size, NULL, NULL);
744 ok(ret, "GetDiskInfoA failed %u\n", GetLastError());
746 ret = GetDiskInfoA(path, NULL, NULL, NULL);
747 ok(ret, "GetDiskInfoA failed %u\n", GetLastError());
749 SetLastError(0xdeadbeef);
750 strcpy(p, "\\non\\existing\\path");
751 ret = GetDiskInfoA(path, NULL, NULL, NULL);
752 error = GetLastError();
753 ok(!ret ||
754 broken(ret), /* < IE7 */
755 "GetDiskInfoA succeeded\n");
756 ok(error == ERROR_PATH_NOT_FOUND ||
757 broken(error == 0xdeadbeef), /* < IE7 */
758 "got %u expected ERROR_PATH_NOT_FOUND\n", error);
760 SetLastError(0xdeadbeef);
761 ret = GetDiskInfoA(NULL, NULL, NULL, NULL);
762 error = GetLastError();
763 ok(!ret, "GetDiskInfoA succeeded\n");
764 ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
767 START_TEST(urlcache)
769 HMODULE hdll;
770 hdll = GetModuleHandleA("wininet.dll");
772 if(!GetProcAddress(hdll, "InternetGetCookieExW")) {
773 win_skip("Too old IE (older than 6.0)\n");
774 return;
777 pDeleteUrlCacheEntryA = (void*)GetProcAddress(hdll, "DeleteUrlCacheEntryA");
778 pUnlockUrlCacheEntryFileA = (void*)GetProcAddress(hdll, "UnlockUrlCacheEntryFileA");
779 test_urlcacheA();
780 test_FindCloseUrlCache();
781 test_GetDiskInfoA();