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 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
35 #include "wine/test.h"
37 static const char test_url
[] = "http://urlcachetest.winehq.org/index.html";
38 static const WCHAR test_urlW
[] = {'h','t','t','p',':','/','/','u','r','l','c','a','c','h','e','t','e','s','t','.',
39 'w','i','n','e','h','q','.','o','r','g','/','i','n','d','e','x','.','h','t','m','l',0};
40 static const char test_url1
[] = "Visited: user@http://urlcachetest.winehq.org/index.html";
41 static const char test_hash_collisions1
[] = "Visited: http://winehq.org/doc0.html";
42 static const char test_hash_collisions2
[] = "Visited: http://winehq.org/doc75651909.html";
44 static BOOL (WINAPI
*pDeleteUrlCacheEntryA
)(LPCSTR
);
45 static BOOL (WINAPI
*pUnlockUrlCacheEntryFileA
)(LPCSTR
,DWORD
);
47 static char filenameA
[MAX_PATH
+ 1];
48 static char filenameA1
[MAX_PATH
+ 1];
49 static BOOL old_ie
= FALSE
;
50 static BOOL ie10_cache
= FALSE
;
52 static void check_cache_entry_infoA(const char *returnedfrom
, INTERNET_CACHE_ENTRY_INFOA
*lpCacheEntryInfo
)
54 ok(lpCacheEntryInfo
->dwStructSize
== sizeof(*lpCacheEntryInfo
), "%s: dwStructSize was %ld\n", returnedfrom
, lpCacheEntryInfo
->dwStructSize
);
55 ok(!strcmp(lpCacheEntryInfo
->lpszSourceUrlName
, test_url
), "%s: lpszSourceUrlName should be %s instead of %s\n", returnedfrom
, test_url
, lpCacheEntryInfo
->lpszSourceUrlName
);
56 ok(!strcmp(lpCacheEntryInfo
->lpszLocalFileName
, filenameA
), "%s: lpszLocalFileName should be %s instead of %s\n", returnedfrom
, filenameA
, lpCacheEntryInfo
->lpszLocalFileName
);
57 ok(!strcmp(lpCacheEntryInfo
->lpszFileExtension
, "html"), "%s: lpszFileExtension should be html instead of %s\n", returnedfrom
, lpCacheEntryInfo
->lpszFileExtension
);
60 static void test_find_url_cache_entriesA(void)
65 DWORD cbCacheEntryInfo
;
66 DWORD cbCacheEntryInfoSaved
;
67 INTERNET_CACHE_ENTRY_INFOA
*lpCacheEntryInfo
;
70 SetLastError(0xdeadbeef);
71 hEnumHandle
= FindFirstUrlCacheEntryA(NULL
, NULL
, &cbCacheEntryInfo
);
72 ok(!hEnumHandle
, "FindFirstUrlCacheEntry should have failed\n");
73 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "FindFirstUrlCacheEntry should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %ld\n", GetLastError());
74 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
* sizeof(char));
75 cbCacheEntryInfoSaved
= cbCacheEntryInfo
;
76 hEnumHandle
= FindFirstUrlCacheEntryA(NULL
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
77 ok(hEnumHandle
!= NULL
, "FindFirstUrlCacheEntry failed with error %ld\n", GetLastError());
80 if (!strcmp(lpCacheEntryInfo
->lpszSourceUrlName
, test_url
))
86 SetLastError(0xdeadbeef);
87 cbCacheEntryInfo
= cbCacheEntryInfoSaved
;
88 ret
= FindNextUrlCacheEntryA(hEnumHandle
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
91 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
93 lpCacheEntryInfo
= HeapReAlloc(GetProcessHeap(), 0, lpCacheEntryInfo
, cbCacheEntryInfo
);
94 cbCacheEntryInfoSaved
= cbCacheEntryInfo
;
95 ret
= FindNextUrlCacheEntryA(hEnumHandle
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
101 ok(ret
, "FindNextUrlCacheEntry failed with error %ld\n", GetLastError());
102 ok(found
, "Committed url cache entry not found during enumeration\n");
104 ret
= FindCloseUrlCache(hEnumHandle
);
105 ok(ret
, "FindCloseUrlCache failed with error %ld\n", GetLastError());
106 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
109 static void test_GetUrlCacheEntryInfoExA(void)
112 DWORD cbCacheEntryInfo
, cbRedirectUrl
;
113 INTERNET_CACHE_ENTRY_INFOA
*lpCacheEntryInfo
;
115 SetLastError(0xdeadbeef);
116 ret
= GetUrlCacheEntryInfoExA(NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
117 ok(!ret
, "GetUrlCacheEntryInfoEx with NULL URL and NULL args should have failed\n");
118 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
119 "GetUrlCacheEntryInfoEx with NULL URL and NULL args should have set last error to ERROR_INVALID_PARAMETER instead of %ld\n", GetLastError());
121 cbCacheEntryInfo
= sizeof(INTERNET_CACHE_ENTRY_INFOA
);
122 SetLastError(0xdeadbeef);
123 ret
= GetUrlCacheEntryInfoExA("", NULL
, &cbCacheEntryInfo
, NULL
, NULL
, NULL
, 0);
124 ok(!ret
, "GetUrlCacheEntryInfoEx with zero-length buffer should fail\n");
125 ok(GetLastError() == ERROR_FILE_NOT_FOUND
,
126 "GetUrlCacheEntryInfoEx should have set last error to ERROR_FILE_NOT_FOUND instead of %ld\n", GetLastError());
128 ret
= GetUrlCacheEntryInfoExA(test_url
, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
129 ok(ret
, "GetUrlCacheEntryInfoEx with NULL args failed with error %ld\n", GetLastError());
131 cbCacheEntryInfo
= 0;
132 SetLastError(0xdeadbeef);
133 ret
= GetUrlCacheEntryInfoExA(test_url
, NULL
, &cbCacheEntryInfo
, NULL
, NULL
, NULL
, 0);
134 ok(!ret
, "GetUrlCacheEntryInfoEx with zero-length buffer should fail\n");
135 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
136 "GetUrlCacheEntryInfoEx should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %ld\n", GetLastError());
138 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
140 SetLastError(0xdeadbeef);
141 ret
= GetUrlCacheEntryInfoExA(test_url
, NULL
, NULL
, NULL
, NULL
, NULL
, 0x200 /*GET_INSTALLED_ENTRY*/);
142 ok(ret
== ie10_cache
, "GetUrlCacheEntryInfoEx returned %x\n", ret
);
143 if (!ret
) ok(GetLastError() == ERROR_FILE_NOT_FOUND
,
144 "GetUrlCacheEntryInfoEx should have set last error to ERROR_FILE_NOT_FOUND instead of %ld\n", GetLastError());
146 /* Unicode version of function seems to ignore 0x200 flag */
147 ret
= GetUrlCacheEntryInfoExW(test_urlW
, NULL
, NULL
, NULL
, NULL
, NULL
, 0x200 /*GET_INSTALLED_ENTRY*/);
148 ok(ret
|| broken(old_ie
&& !ret
), "GetUrlCacheEntryInfoExW failed with error %ld\n", GetLastError());
150 ret
= GetUrlCacheEntryInfoExA(test_url
, lpCacheEntryInfo
, &cbCacheEntryInfo
, NULL
, NULL
, NULL
, 0);
151 ok(ret
, "GetUrlCacheEntryInfoEx failed with error %ld\n", GetLastError());
153 if (ret
) check_cache_entry_infoA("GetUrlCacheEntryInfoEx", lpCacheEntryInfo
);
155 lpCacheEntryInfo
->CacheEntryType
|= 0x10000000; /* INSTALLED_CACHE_ENTRY */
156 ret
= SetUrlCacheEntryInfoA(test_url
, lpCacheEntryInfo
, CACHE_ENTRY_ATTRIBUTE_FC
);
157 ok(ret
, "SetUrlCacheEntryInfoA failed with error %ld\n", GetLastError());
159 SetLastError(0xdeadbeef);
160 ret
= GetUrlCacheEntryInfoExA(test_url
, NULL
, NULL
, NULL
, NULL
, NULL
, 0x200 /*GET_INSTALLED_ENTRY*/);
161 ok(ret
, "GetUrlCacheEntryInfoEx failed with error %ld\n", GetLastError());
163 cbCacheEntryInfo
= 100000;
164 SetLastError(0xdeadbeef);
165 ret
= GetUrlCacheEntryInfoExA(test_url
, NULL
, &cbCacheEntryInfo
, NULL
, NULL
, NULL
, 0);
166 ok(!ret
, "GetUrlCacheEntryInfoEx with zero-length buffer should fail\n");
167 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "GetUrlCacheEntryInfoEx should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %ld\n", GetLastError());
169 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
171 /* Querying the redirect URL fails with ERROR_INVALID_PARAMETER */
172 SetLastError(0xdeadbeef);
173 ret
= GetUrlCacheEntryInfoExA(test_url
, NULL
, NULL
, NULL
, &cbRedirectUrl
, NULL
, 0);
174 ok(!ret
, "GetUrlCacheEntryInfoEx should have failed\n");
175 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
176 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
177 SetLastError(0xdeadbeef);
178 ret
= GetUrlCacheEntryInfoExA(test_url
, NULL
, &cbCacheEntryInfo
, NULL
, &cbRedirectUrl
, NULL
, 0);
179 ok(!ret
, "GetUrlCacheEntryInfoEx should have failed\n");
180 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
181 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
184 static void test_RetrieveUrlCacheEntryA(void)
187 DWORD cbCacheEntryInfo
;
189 cbCacheEntryInfo
= 0;
190 SetLastError(0xdeadbeef);
191 ret
= RetrieveUrlCacheEntryFileA(NULL
, NULL
, &cbCacheEntryInfo
, 0);
192 ok(!ret
, "RetrieveUrlCacheEntryFile should have failed\n");
193 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "RetrieveUrlCacheEntryFile should have set last error to ERROR_INVALID_PARAMETER instead of %ld\n", GetLastError());
197 /* Crashes on Win9x, NT4 and W2K */
198 SetLastError(0xdeadbeef);
199 ret
= RetrieveUrlCacheEntryFileA(test_url
, NULL
, NULL
, 0);
200 ok(!ret
, "RetrieveUrlCacheEntryFile should have failed\n");
201 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "RetrieveUrlCacheEntryFile should have set last error to ERROR_INVALID_PARAMETER instead of %ld\n", GetLastError());
204 SetLastError(0xdeadbeef);
205 cbCacheEntryInfo
= 100000;
206 ret
= RetrieveUrlCacheEntryFileA(NULL
, NULL
, &cbCacheEntryInfo
, 0);
207 ok(!ret
, "RetrieveUrlCacheEntryFile should have failed\n");
208 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "RetrieveUrlCacheEntryFile should have set last error to ERROR_INVALID_PARAMETER instead of %ld\n", GetLastError());
211 static void test_IsUrlCacheEntryExpiredA(void)
213 static const char uncached_url
[] =
214 "What's the airspeed velocity of an unladen swallow?";
218 INTERNET_CACHE_ENTRY_INFOA
*info
;
219 ULARGE_INTEGER exp_time
;
221 /* The function returns TRUE when the output time is NULL or the tested URL
224 ret
= IsUrlCacheEntryExpiredA(NULL
, 0, NULL
);
225 ok(ret
!= ie10_cache
, "IsUrlCacheEntryExpiredA returned %x\n", ret
);
226 ft
.dwLowDateTime
= 0xdeadbeef;
227 ft
.dwHighDateTime
= 0xbaadf00d;
228 ret
= IsUrlCacheEntryExpiredA(NULL
, 0, &ft
);
229 ok(ret
!= ie10_cache
, "IsUrlCacheEntryExpiredA returned %x\n", ret
);
230 ok(ft
.dwLowDateTime
== 0xdeadbeef && ft
.dwHighDateTime
== 0xbaadf00d,
231 "expected time to be unchanged, got (%lu,%lu)\n",
232 ft
.dwLowDateTime
, ft
.dwHighDateTime
);
233 ret
= IsUrlCacheEntryExpiredA(test_url
, 0, NULL
);
234 ok(ret
!= ie10_cache
, "IsUrlCacheEntryExpiredA returned %x\n", ret
);
236 /* The return value should indicate whether the URL is expired,
237 * and the filetime indicates the last modified time, but a cache entry
238 * with a zero expire time is "not expired".
240 ft
.dwLowDateTime
= 0xdeadbeef;
241 ft
.dwHighDateTime
= 0xbaadf00d;
242 ret
= IsUrlCacheEntryExpiredA(test_url
, 0, &ft
);
243 ok(!ret
, "expected FALSE\n");
244 ok(!ft
.dwLowDateTime
&& !ft
.dwHighDateTime
,
245 "expected time (0,0), got (%lu,%lu)\n",
246 ft
.dwLowDateTime
, ft
.dwHighDateTime
);
248 /* Same behavior with bogus flags. */
249 ft
.dwLowDateTime
= 0xdeadbeef;
250 ft
.dwHighDateTime
= 0xbaadf00d;
251 ret
= IsUrlCacheEntryExpiredA(test_url
, 0xffffffff, &ft
);
252 ok(!ret
, "expected FALSE\n");
253 ok(!ft
.dwLowDateTime
&& !ft
.dwHighDateTime
,
254 "expected time (0,0), got (%lu,%lu)\n",
255 ft
.dwLowDateTime
, ft
.dwHighDateTime
);
257 /* Set the expire time to a point in the past.. */
258 ret
= GetUrlCacheEntryInfoA(test_url
, NULL
, &size
);
259 ok(!ret
, "GetUrlCacheEntryInfo should have failed\n");
260 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
261 "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
262 info
= HeapAlloc(GetProcessHeap(), 0, size
);
263 ret
= GetUrlCacheEntryInfoA(test_url
, info
, &size
);
264 ok(ret
, "GetUrlCacheEntryInfo failed: %ld\n", GetLastError());
265 GetSystemTimeAsFileTime(&info
->ExpireTime
);
266 exp_time
.u
.LowPart
= info
->ExpireTime
.dwLowDateTime
;
267 exp_time
.u
.HighPart
= info
->ExpireTime
.dwHighDateTime
;
268 exp_time
.QuadPart
-= 10 * 60 * (ULONGLONG
)10000000;
269 info
->ExpireTime
.dwLowDateTime
= exp_time
.u
.LowPart
;
270 info
->ExpireTime
.dwHighDateTime
= exp_time
.u
.HighPart
;
271 ret
= SetUrlCacheEntryInfoA(test_url
, info
, CACHE_ENTRY_EXPTIME_FC
);
272 ok(ret
, "SetUrlCacheEntryInfo failed: %ld\n", GetLastError());
273 ft
.dwLowDateTime
= 0xdeadbeef;
274 ft
.dwHighDateTime
= 0xbaadf00d;
275 /* and the entry should be expired. */
276 ret
= IsUrlCacheEntryExpiredA(test_url
, 0, &ft
);
277 ok(ret
, "expected TRUE\n");
278 /* The modified time returned is 0. */
279 ok(!ft
.dwLowDateTime
&& !ft
.dwHighDateTime
,
280 "expected time (0,0), got (%lu,%lu)\n",
281 ft
.dwLowDateTime
, ft
.dwHighDateTime
);
282 /* Set the expire time to a point in the future.. */
283 exp_time
.QuadPart
+= 20 * 60 * (ULONGLONG
)10000000;
284 info
->ExpireTime
.dwLowDateTime
= exp_time
.u
.LowPart
;
285 info
->ExpireTime
.dwHighDateTime
= exp_time
.u
.HighPart
;
286 ret
= SetUrlCacheEntryInfoA(test_url
, info
, CACHE_ENTRY_EXPTIME_FC
);
287 ok(ret
, "SetUrlCacheEntryInfo failed: %ld\n", GetLastError());
288 ft
.dwLowDateTime
= 0xdeadbeef;
289 ft
.dwHighDateTime
= 0xbaadf00d;
290 /* and the entry should no longer be expired. */
291 ret
= IsUrlCacheEntryExpiredA(test_url
, 0, &ft
);
292 ok(!ret
, "expected FALSE\n");
293 /* The modified time returned is still 0. */
294 ok(!ft
.dwLowDateTime
&& !ft
.dwHighDateTime
,
295 "expected time (0,0), got (%lu,%lu)\n",
296 ft
.dwLowDateTime
, ft
.dwHighDateTime
);
297 /* Set the modified time... */
298 GetSystemTimeAsFileTime(&info
->LastModifiedTime
);
299 ret
= SetUrlCacheEntryInfoA(test_url
, info
, CACHE_ENTRY_MODTIME_FC
);
300 ok(ret
, "SetUrlCacheEntryInfo failed: %ld\n", GetLastError());
301 /* and the entry should still be unexpired.. */
302 ret
= IsUrlCacheEntryExpiredA(test_url
, 0, &ft
);
303 ok(!ret
, "expected FALSE\n");
304 /* but the modified time returned is the last modified time just set. */
305 ok(ft
.dwLowDateTime
== info
->LastModifiedTime
.dwLowDateTime
&&
306 ft
.dwHighDateTime
== info
->LastModifiedTime
.dwHighDateTime
,
307 "expected time (%lu,%lu), got (%lu,%lu)\n",
308 info
->LastModifiedTime
.dwLowDateTime
,
309 info
->LastModifiedTime
.dwHighDateTime
,
310 ft
.dwLowDateTime
, ft
.dwHighDateTime
);
311 HeapFree(GetProcessHeap(), 0, info
);
313 /* An uncached URL is implicitly expired, but with unknown time. */
314 ft
.dwLowDateTime
= 0xdeadbeef;
315 ft
.dwHighDateTime
= 0xbaadf00d;
316 ret
= IsUrlCacheEntryExpiredA(uncached_url
, 0, &ft
);
317 ok(ret
!= ie10_cache
, "IsUrlCacheEntryExpiredA returned %x\n", ret
);
318 ok(!ft
.dwLowDateTime
&& !ft
.dwHighDateTime
,
319 "expected time (0,0), got (%lu,%lu)\n",
320 ft
.dwLowDateTime
, ft
.dwHighDateTime
);
323 static void _check_file_exists(LONG l
, LPCSTR filename
)
327 file
= CreateFileA(filename
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
328 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
329 ok_(__FILE__
,l
)(file
!= INVALID_HANDLE_VALUE
,
330 "expected file to exist, CreateFile failed with error %ld\n",
335 #define check_file_exists(f) _check_file_exists(__LINE__, f)
337 static void _check_file_not_exists(LONG l
, LPCSTR filename
)
341 file
= CreateFileA(filename
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
342 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
343 ok_(__FILE__
,l
)(file
== INVALID_HANDLE_VALUE
,
344 "expected file not to exist\n");
345 if (file
!= INVALID_HANDLE_VALUE
)
349 #define check_file_not_exists(f) _check_file_not_exists(__LINE__, f)
351 static void create_and_write_file(LPCSTR filename
, void *data
, DWORD len
)
357 file
= CreateFileA(filename
, GENERIC_WRITE
,
358 FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, CREATE_ALWAYS
,
359 FILE_ATTRIBUTE_NORMAL
, NULL
);
360 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFileA failed with error %ld\n", GetLastError());
362 ret
= WriteFile(file
, data
, len
, &written
, NULL
);
363 ok(ret
, "WriteFile failed with error %ld\n", GetLastError());
368 static void test_urlcacheA(void)
370 static char long_url
[300] = "http://www.winehq.org/";
371 static char ok_header
[] = "HTTP/1.0 200 OK\r\n\r\n";
375 INTERNET_CACHE_ENTRY_INFOA
*lpCacheEntryInfo
;
376 INTERNET_CACHE_ENTRY_INFOA
*lpCacheEntryInfo2
;
377 DWORD cbCacheEntryInfo
;
378 static const FILETIME filetime_zero
;
382 ret
= CreateUrlCacheEntryA(test_url
, 0, "html", filenameA
, 0);
383 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
385 ret
= CreateUrlCacheEntryA(test_url
, 0, "html", filenameA1
, 0);
386 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
387 check_file_exists(filenameA1
);
388 DeleteFileA(filenameA1
);
390 ok(lstrcmpiA(filenameA
, filenameA1
), "expected a different file name\n");
392 create_and_write_file(filenameA
, &zero_byte
, sizeof(zero_byte
));
394 ret
= CommitUrlCacheEntryA(test_url1
, NULL
, filetime_zero
, filetime_zero
, NORMAL_CACHE_ENTRY
, NULL
, 0, "html", NULL
);
395 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
396 cbCacheEntryInfo
= 0;
397 ret
= GetUrlCacheEntryInfoA(test_url1
, NULL
, &cbCacheEntryInfo
);
398 ok(!ret
, "GetUrlCacheEntryInfo should have failed\n");
399 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
400 "GetUrlCacheEntryInfo should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %ld\n", GetLastError());
401 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
402 ret
= GetUrlCacheEntryInfoA(test_url1
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
403 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
404 ok(!memcmp(&lpCacheEntryInfo
->ExpireTime
, &filetime_zero
, sizeof(FILETIME
)),
405 "expected zero ExpireTime\n");
406 ok(!memcmp(&lpCacheEntryInfo
->LastModifiedTime
, &filetime_zero
, sizeof(FILETIME
)),
407 "expected zero LastModifiedTime\n");
408 ok(lpCacheEntryInfo
->CacheEntryType
== (NORMAL_CACHE_ENTRY
|URLHISTORY_CACHE_ENTRY
) ||
409 broken(lpCacheEntryInfo
->CacheEntryType
== NORMAL_CACHE_ENTRY
/* NT4/W2k */),
410 "expected type NORMAL_CACHE_ENTRY|URLHISTORY_CACHE_ENTRY, got %08lx\n",
411 lpCacheEntryInfo
->CacheEntryType
);
412 ok(!U(*lpCacheEntryInfo
).dwExemptDelta
, "expected dwExemptDelta 0, got %ld\n",
413 U(*lpCacheEntryInfo
).dwExemptDelta
);
415 /* Make sure there is a notable change in timestamps */
418 /* A subsequent commit with a different time/type doesn't change most of the entry */
419 GetSystemTimeAsFileTime(&now
);
420 ret
= CommitUrlCacheEntryA(test_url1
, NULL
, now
, now
, NORMAL_CACHE_ENTRY
,
421 (LPBYTE
)ok_header
, strlen(ok_header
), NULL
, NULL
);
422 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
423 cbCacheEntryInfo
= 0;
424 ret
= GetUrlCacheEntryInfoA(test_url1
, NULL
, &cbCacheEntryInfo
);
425 ok(!ret
, "GetUrlCacheEntryInfo should have failed\n");
426 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
427 "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
428 lpCacheEntryInfo2
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
429 ret
= GetUrlCacheEntryInfoA(test_url1
, lpCacheEntryInfo2
, &cbCacheEntryInfo
);
430 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
431 /* but it does change the time.. */
432 ok(memcmp(&lpCacheEntryInfo2
->ExpireTime
, &filetime_zero
, sizeof(FILETIME
)),
433 "expected positive ExpireTime\n");
434 ok(memcmp(&lpCacheEntryInfo2
->LastModifiedTime
, &filetime_zero
, sizeof(FILETIME
)),
435 "expected positive LastModifiedTime\n");
436 ok(lpCacheEntryInfo2
->CacheEntryType
== (NORMAL_CACHE_ENTRY
|URLHISTORY_CACHE_ENTRY
) ||
437 broken(lpCacheEntryInfo2
->CacheEntryType
== NORMAL_CACHE_ENTRY
/* NT4/W2k */),
438 "expected type NORMAL_CACHE_ENTRY|URLHISTORY_CACHE_ENTRY, got %08lx\n",
439 lpCacheEntryInfo2
->CacheEntryType
);
440 /* and set the headers. */
441 ok(lpCacheEntryInfo2
->dwHeaderInfoSize
== 19,
442 "expected headers size 19, got %ld\n",
443 lpCacheEntryInfo2
->dwHeaderInfoSize
);
444 /* Hit rate gets incremented by 1 */
445 ok((lpCacheEntryInfo
->dwHitRate
+ 1) == lpCacheEntryInfo2
->dwHitRate
,
446 "HitRate not incremented by one on commit\n");
447 /* Last access time should be updated */
448 ok(!(lpCacheEntryInfo
->LastAccessTime
.dwHighDateTime
== lpCacheEntryInfo2
->LastAccessTime
.dwHighDateTime
&&
449 lpCacheEntryInfo
->LastAccessTime
.dwLowDateTime
== lpCacheEntryInfo2
->LastAccessTime
.dwLowDateTime
),
450 "Last accessed time was not updated by commit\n");
451 /* File extension should be unset */
452 ok(lpCacheEntryInfo2
->lpszFileExtension
== NULL
,
453 "Fileextension isn't unset: %s\n",
454 lpCacheEntryInfo2
->lpszFileExtension
);
455 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
456 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo2
);
458 ret
= CommitUrlCacheEntryA(test_url
, filenameA
, filetime_zero
, filetime_zero
, NORMAL_CACHE_ENTRY
, NULL
, 0, "html", NULL
);
459 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
461 cbCacheEntryInfo
= 0;
462 SetLastError(0xdeadbeef);
463 ret
= RetrieveUrlCacheEntryFileA(test_url
, NULL
, &cbCacheEntryInfo
, 0);
464 ok(!ret
, "RetrieveUrlCacheEntryFile should have failed\n");
465 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
466 "RetrieveUrlCacheEntryFile should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %ld\n", GetLastError());
468 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
469 ret
= RetrieveUrlCacheEntryFileA(test_url
, lpCacheEntryInfo
, &cbCacheEntryInfo
, 0);
470 ok(ret
, "RetrieveUrlCacheEntryFile failed with error %ld\n", GetLastError());
472 if (ret
) check_cache_entry_infoA("RetrieveUrlCacheEntryFile", lpCacheEntryInfo
);
474 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
476 cbCacheEntryInfo
= 0;
477 SetLastError(0xdeadbeef);
478 ret
= RetrieveUrlCacheEntryFileA(test_url1
, NULL
, &cbCacheEntryInfo
, 0);
479 ok(!ret
, "RetrieveUrlCacheEntryFile should have failed\n");
480 ok(GetLastError() == ERROR_INVALID_DATA
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
481 "RetrieveUrlCacheEntryFile should have set last error to ERROR_INVALID_DATA instead of %ld\n", GetLastError());
483 if (pUnlockUrlCacheEntryFileA
)
485 ret
= pUnlockUrlCacheEntryFileA(test_url
, 0);
486 ok(ret
, "UnlockUrlCacheEntryFileA failed with error %ld\n", GetLastError());
489 /* test Find*UrlCacheEntry functions */
490 test_find_url_cache_entriesA();
492 test_GetUrlCacheEntryInfoExA();
493 test_RetrieveUrlCacheEntryA();
494 test_IsUrlCacheEntryExpiredA();
496 if (pDeleteUrlCacheEntryA
)
498 ret
= pDeleteUrlCacheEntryA(test_url
);
499 ok(ret
, "DeleteUrlCacheEntryA failed with error %ld\n", GetLastError());
500 ret
= pDeleteUrlCacheEntryA(test_url1
);
501 ok(ret
, "DeleteUrlCacheEntryA failed with error %ld\n", GetLastError());
504 SetLastError(0xdeadbeef);
505 ret
= DeleteFileA(filenameA
);
506 ok(!ret
&& GetLastError() == ERROR_FILE_NOT_FOUND
, "local file should no longer exist\n");
508 /* Creating two entries with the same URL */
509 ret
= CreateUrlCacheEntryA(test_url
, 0, "html", filenameA
, 0);
510 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
512 ret
= CreateUrlCacheEntryA(test_url
, 0, "html", filenameA1
, 0);
513 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
515 ok(lstrcmpiA(filenameA
, filenameA1
), "expected a different file name\n");
517 create_and_write_file(filenameA
, &zero_byte
, sizeof(zero_byte
));
518 create_and_write_file(filenameA1
, &zero_byte
, sizeof(zero_byte
));
519 check_file_exists(filenameA
);
520 check_file_exists(filenameA1
);
522 ret
= CommitUrlCacheEntryA(test_url
, filenameA
, filetime_zero
,
523 filetime_zero
, NORMAL_CACHE_ENTRY
, (LPBYTE
)ok_header
,
524 strlen(ok_header
), "html", NULL
);
525 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
526 check_file_exists(filenameA
);
527 check_file_exists(filenameA1
);
528 ret
= CommitUrlCacheEntryA(test_url
, filenameA1
, filetime_zero
,
529 filetime_zero
, COOKIE_CACHE_ENTRY
, NULL
, 0, "html", NULL
);
530 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
531 /* By committing the same URL a second time, the prior entry is
534 cbCacheEntryInfo
= 0;
535 SetLastError(0xdeadbeef);
536 ret
= GetUrlCacheEntryInfoA(test_url
, NULL
, &cbCacheEntryInfo
);
537 ok(!ret
, "GetUrlCacheEntryInfo should have failed\n");
538 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
539 "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
540 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
541 ret
= GetUrlCacheEntryInfoA(test_url
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
542 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
543 /* with the previous entry type retained.. */
544 ok(lpCacheEntryInfo
->CacheEntryType
& NORMAL_CACHE_ENTRY
,
545 "expected cache entry type NORMAL_CACHE_ENTRY, got %ld (0x%08lx)\n",
546 lpCacheEntryInfo
->CacheEntryType
, lpCacheEntryInfo
->CacheEntryType
);
547 /* and the headers overwritten.. */
548 ok(!lpCacheEntryInfo
->dwHeaderInfoSize
, "expected headers size 0, got %ld\n",
549 lpCacheEntryInfo
->dwHeaderInfoSize
);
550 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
551 /* and the previous filename shouldn't exist. */
552 check_file_not_exists(filenameA
);
553 check_file_exists(filenameA1
);
555 if (pDeleteUrlCacheEntryA
)
557 ret
= pDeleteUrlCacheEntryA(test_url
);
558 ok(ret
, "DeleteUrlCacheEntryA failed with error %ld\n", GetLastError());
559 check_file_not_exists(filenameA
);
560 check_file_not_exists(filenameA1
);
561 /* Just in case, clean up files */
562 DeleteFileA(filenameA1
);
563 DeleteFileA(filenameA
);
566 /* Check whether a retrieved cache entry can be deleted before it's
569 ret
= CreateUrlCacheEntryA(test_url
, 0, "html", filenameA
, 0);
570 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
571 ret
= CommitUrlCacheEntryA(test_url
, filenameA
, filetime_zero
, filetime_zero
,
572 NORMAL_CACHE_ENTRY
, NULL
, 0, "html", NULL
);
573 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
575 cbCacheEntryInfo
= 0;
576 SetLastError(0xdeadbeef);
577 ret
= RetrieveUrlCacheEntryFileA(test_url
, NULL
, &cbCacheEntryInfo
, 0);
578 ok(!ret
, "RetrieveUrlCacheEntryFile should have failed\n");
579 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
580 "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
582 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
583 ret
= RetrieveUrlCacheEntryFileA(test_url
, lpCacheEntryInfo
,
584 &cbCacheEntryInfo
, 0);
585 ok(ret
, "RetrieveUrlCacheEntryFile failed with error %ld\n", GetLastError());
587 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
589 if (pDeleteUrlCacheEntryA
)
591 ret
= pDeleteUrlCacheEntryA(test_url
);
592 ok(!ret
, "Expected failure\n");
593 ok(GetLastError() == ERROR_SHARING_VIOLATION
,
594 "Expected ERROR_SHARING_VIOLATION, got %ld\n", GetLastError());
595 check_file_exists(filenameA
);
598 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
599 memset(lpCacheEntryInfo
, 0, cbCacheEntryInfo
);
600 ret
= GetUrlCacheEntryInfoA(test_url
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
601 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
602 ok(lpCacheEntryInfo
->CacheEntryType
& 0x400000,
603 "CacheEntryType hasn't PENDING_DELETE_CACHE_ENTRY set, (flags %08lx)\n",
604 lpCacheEntryInfo
->CacheEntryType
);
605 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
607 if (pUnlockUrlCacheEntryFileA
)
609 check_file_exists(filenameA
);
610 ret
= pUnlockUrlCacheEntryFileA(test_url
, 0);
611 ok(ret
, "UnlockUrlCacheEntryFileA failed: %ld\n", GetLastError());
612 /* By unlocking the already-deleted cache entry, the file associated
613 * with it is deleted..
615 check_file_not_exists(filenameA
);
616 /* (just in case, delete file) */
617 DeleteFileA(filenameA
);
619 if (pDeleteUrlCacheEntryA
)
621 /* and a subsequent deletion should fail. */
622 ret
= pDeleteUrlCacheEntryA(test_url
);
623 ok(!ret
, "Expected failure\n");
624 ok(GetLastError() == ERROR_FILE_NOT_FOUND
,
625 "expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
628 /* Test whether preventing a file from being deleted causes
629 * DeleteUrlCacheEntryA to fail.
631 ret
= CreateUrlCacheEntryA(test_url
, 0, "html", filenameA
, 0);
632 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
634 create_and_write_file(filenameA
, &zero_byte
, sizeof(zero_byte
));
635 check_file_exists(filenameA
);
637 ret
= CommitUrlCacheEntryA(test_url
, filenameA
, filetime_zero
,
638 filetime_zero
, NORMAL_CACHE_ENTRY
, (LPBYTE
)ok_header
,
639 strlen(ok_header
), "html", NULL
);
640 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
641 check_file_exists(filenameA
);
642 hFile
= CreateFileA(filenameA
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
643 FILE_ATTRIBUTE_NORMAL
, NULL
);
644 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA failed: %ld\n",
646 if (pDeleteUrlCacheEntryA
)
648 /* DeleteUrlCacheEntryA should succeed.. */
649 ret
= pDeleteUrlCacheEntryA(test_url
);
650 ok(ret
, "DeleteUrlCacheEntryA failed with error %ld\n", GetLastError());
653 if (pDeleteUrlCacheEntryA
)
655 /* and a subsequent deletion should fail.. */
656 ret
= pDeleteUrlCacheEntryA(test_url
);
657 ok(!ret
, "Expected failure\n");
658 ok(GetLastError() == ERROR_FILE_NOT_FOUND
,
659 "expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
661 /* and the file should be untouched. */
662 check_file_exists(filenameA
);
663 DeleteFileA(filenameA
);
665 /* Try creating a sticky entry. Unlike non-sticky entries, the filename
666 * must have been set already.
668 SetLastError(0xdeadbeef);
669 ret
= CommitUrlCacheEntryA(test_url
, NULL
, filetime_zero
, filetime_zero
,
670 STICKY_CACHE_ENTRY
, (LPBYTE
)ok_header
, strlen(ok_header
), "html",
672 ok(ret
== ie10_cache
, "CommitUrlCacheEntryA returned %x\n", ret
);
673 if (!ret
) ok(GetLastError() == ERROR_INVALID_PARAMETER
,
674 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
675 SetLastError(0xdeadbeef);
676 ret
= CommitUrlCacheEntryA(test_url
, NULL
, filetime_zero
, filetime_zero
,
677 NORMAL_CACHE_ENTRY
|STICKY_CACHE_ENTRY
,
678 (LPBYTE
)ok_header
, strlen(ok_header
), "html", NULL
);
679 ok(ret
== ie10_cache
, "CommitUrlCacheEntryA returned %x\n", ret
);
680 if (!ret
) ok(GetLastError() == ERROR_INVALID_PARAMETER
,
681 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
683 ret
= CreateUrlCacheEntryA(test_url
, 0, "html", filenameA
, 0);
684 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
685 create_and_write_file(filenameA
, &zero_byte
, sizeof(zero_byte
));
686 ret
= CommitUrlCacheEntryA(test_url
, filenameA
, filetime_zero
, filetime_zero
,
687 NORMAL_CACHE_ENTRY
|STICKY_CACHE_ENTRY
,
688 (LPBYTE
)ok_header
, strlen(ok_header
), "html", NULL
);
689 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
690 cbCacheEntryInfo
= 0;
691 SetLastError(0xdeadbeef);
692 ret
= GetUrlCacheEntryInfoA(test_url
, NULL
, &cbCacheEntryInfo
);
693 ok(!ret
, "GetUrlCacheEntryInfo should have failed\n");
694 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
695 "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
696 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
697 ret
= GetUrlCacheEntryInfoA(test_url
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
698 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
699 ok(lpCacheEntryInfo
->CacheEntryType
& (NORMAL_CACHE_ENTRY
|STICKY_CACHE_ENTRY
),
700 "expected cache entry type NORMAL_CACHE_ENTRY | STICKY_CACHE_ENTRY, got %ld (0x%08lx)\n",
701 lpCacheEntryInfo
->CacheEntryType
, lpCacheEntryInfo
->CacheEntryType
);
702 ok(U(*lpCacheEntryInfo
).dwExemptDelta
== 86400,
703 "expected dwExemptDelta 86400, got %ld\n",
704 U(*lpCacheEntryInfo
).dwExemptDelta
);
705 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
706 if (pDeleteUrlCacheEntryA
)
708 ret
= pDeleteUrlCacheEntryA(test_url
);
709 ok(ret
, "DeleteUrlCacheEntryA failed with error %ld\n", GetLastError());
710 /* When explicitly deleting the cache entry, the file is also deleted */
711 check_file_not_exists(filenameA
);
713 /* Test once again, setting the exempt delta via SetUrlCacheEntryInfo */
714 ret
= CreateUrlCacheEntryA(test_url
, 0, "html", filenameA
, 0);
715 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
716 create_and_write_file(filenameA
, &zero_byte
, sizeof(zero_byte
));
717 ret
= CommitUrlCacheEntryA(test_url
, filenameA
, filetime_zero
, filetime_zero
,
718 NORMAL_CACHE_ENTRY
|STICKY_CACHE_ENTRY
,
719 (LPBYTE
)ok_header
, strlen(ok_header
), "html", NULL
);
720 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
721 cbCacheEntryInfo
= 0;
722 SetLastError(0xdeadbeef);
723 ret
= GetUrlCacheEntryInfoA(test_url
, NULL
, &cbCacheEntryInfo
);
724 ok(!ret
, "GetUrlCacheEntryInfo should have failed\n");
725 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
726 "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
727 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
728 ret
= GetUrlCacheEntryInfoA(test_url
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
729 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
730 ok(lpCacheEntryInfo
->CacheEntryType
& (NORMAL_CACHE_ENTRY
|STICKY_CACHE_ENTRY
),
731 "expected cache entry type NORMAL_CACHE_ENTRY | STICKY_CACHE_ENTRY, got %ld (0x%08lx)\n",
732 lpCacheEntryInfo
->CacheEntryType
, lpCacheEntryInfo
->CacheEntryType
);
733 ok(U(*lpCacheEntryInfo
).dwExemptDelta
== 86400,
734 "expected dwExemptDelta 86400, got %ld\n",
735 U(*lpCacheEntryInfo
).dwExemptDelta
);
736 U(*lpCacheEntryInfo
).dwExemptDelta
= 0;
737 ret
= SetUrlCacheEntryInfoA(test_url
, lpCacheEntryInfo
,
738 CACHE_ENTRY_EXEMPT_DELTA_FC
);
739 ok(ret
, "SetUrlCacheEntryInfo failed: %ld\n", GetLastError());
740 ret
= GetUrlCacheEntryInfoA(test_url
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
741 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
742 ok(!U(*lpCacheEntryInfo
).dwExemptDelta
, "expected dwExemptDelta 0, got %ld\n",
743 U(*lpCacheEntryInfo
).dwExemptDelta
);
744 /* See whether a sticky cache entry has the flag cleared once the exempt
745 * delta is meaningless.
747 ok(lpCacheEntryInfo
->CacheEntryType
& (NORMAL_CACHE_ENTRY
|STICKY_CACHE_ENTRY
),
748 "expected cache entry type NORMAL_CACHE_ENTRY | STICKY_CACHE_ENTRY, got %ld (0x%08lx)\n",
749 lpCacheEntryInfo
->CacheEntryType
, lpCacheEntryInfo
->CacheEntryType
);
751 /* Recommit of Url entry keeps dwExemptDelta */
752 U(*lpCacheEntryInfo
).dwExemptDelta
= 8600;
753 ret
= SetUrlCacheEntryInfoA(test_url
, lpCacheEntryInfo
,
754 CACHE_ENTRY_EXEMPT_DELTA_FC
);
755 ok(ret
, "SetUrlCacheEntryInfo failed: %ld\n", GetLastError());
757 ret
= CreateUrlCacheEntryA(test_url
, 0, "html", filenameA1
, 0);
758 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
759 create_and_write_file(filenameA1
, &zero_byte
, sizeof(zero_byte
));
761 ret
= CommitUrlCacheEntryA(test_url
, filenameA1
, filetime_zero
, filetime_zero
,
762 NORMAL_CACHE_ENTRY
|STICKY_CACHE_ENTRY
,
763 (LPBYTE
)ok_header
, strlen(ok_header
), "html", NULL
);
764 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
766 ret
= GetUrlCacheEntryInfoA(test_url
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
767 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
768 ok(U(*lpCacheEntryInfo
).dwExemptDelta
== 8600 || (ie10_cache
&& U(*lpCacheEntryInfo
).dwExemptDelta
== 86400),
769 "expected dwExemptDelta 8600, got %ld\n", U(*lpCacheEntryInfo
).dwExemptDelta
);
771 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
773 if (pDeleteUrlCacheEntryA
)
775 ret
= pDeleteUrlCacheEntryA(test_url
);
776 ok(ret
, "DeleteUrlCacheEntryA failed with error %ld\n", GetLastError());
777 check_file_not_exists(filenameA
);
780 /* Test if files with identical hash keys are handled correctly */
781 ret
= CommitUrlCacheEntryA(test_hash_collisions1
, NULL
, filetime_zero
, filetime_zero
, NORMAL_CACHE_ENTRY
, NULL
, 0, "html", NULL
);
782 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
783 ret
= CommitUrlCacheEntryA(test_hash_collisions2
, NULL
, filetime_zero
, filetime_zero
, NORMAL_CACHE_ENTRY
, NULL
, 0, "html", NULL
);
784 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
786 cbCacheEntryInfo
= 0;
787 ret
= GetUrlCacheEntryInfoA(test_hash_collisions1
, NULL
, &cbCacheEntryInfo
);
788 ok(!ret
, "GetUrlCacheEntryInfo should have failed\n");
789 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
790 "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
791 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
792 ret
= GetUrlCacheEntryInfoA(test_hash_collisions1
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
793 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
794 ok(!strcmp(lpCacheEntryInfo
->lpszSourceUrlName
, test_hash_collisions1
),
795 "got incorrect entry: %s\n", lpCacheEntryInfo
->lpszSourceUrlName
);
796 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
798 cbCacheEntryInfo
= 0;
799 ret
= GetUrlCacheEntryInfoA(test_hash_collisions2
, NULL
, &cbCacheEntryInfo
);
800 ok(!ret
, "GetUrlCacheEntryInfo should have failed\n");
801 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
802 "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
803 lpCacheEntryInfo
= HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo
);
804 ret
= GetUrlCacheEntryInfoA(test_hash_collisions2
, lpCacheEntryInfo
, &cbCacheEntryInfo
);
805 ok(ret
, "GetUrlCacheEntryInfo failed with error %ld\n", GetLastError());
806 ok(!strcmp(lpCacheEntryInfo
->lpszSourceUrlName
, test_hash_collisions2
),
807 "got incorrect entry: %s\n", lpCacheEntryInfo
->lpszSourceUrlName
);
808 HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo
);
810 if (pDeleteUrlCacheEntryA
) {
811 ret
= pDeleteUrlCacheEntryA(test_hash_collisions1
);
812 ok(ret
, "DeleteUrlCacheEntry failed: %ld\n", GetLastError());
813 ret
= pDeleteUrlCacheEntryA(test_hash_collisions2
);
814 ok(ret
, "DeleteUrlCacheEntry failed: %ld\n", GetLastError());
817 len
= strlen(long_url
);
818 memset(long_url
+len
, 'a', sizeof(long_url
)-len
);
819 long_url
[sizeof(long_url
)-1] = 0;
820 ret
= CreateUrlCacheEntryA(long_url
, 0, NULL
, filenameA
, 0);
821 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
822 check_file_exists(filenameA
);
823 DeleteFileA(filenameA
);
825 ret
= CreateUrlCacheEntryA(long_url
, 0, "extension", filenameA
, 0);
826 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
827 check_file_exists(filenameA
);
828 DeleteFileA(filenameA
);
831 ret
= CreateUrlCacheEntryA(long_url
, 0, NULL
, filenameA
, 0);
832 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
833 check_file_exists(filenameA
);
834 DeleteFileA(filenameA
);
836 ret
= CreateUrlCacheEntryA(long_url
, 0, "extension", filenameA
, 0);
837 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
838 check_file_exists(filenameA
);
839 DeleteFileA(filenameA
);
842 static void test_urlcacheW(void)
844 static struct test_data
848 char encoded_url
[128];
850 WCHAR header_info
[128];
853 0, {'h','t','t','p',':','/','/','T','.','p','l','/','t',0},
854 "http://T.pl/t", {0}, {0}
857 0, {'w','w','w','.','T','.','p','l','/','t',0},
858 "www.T.pl/t", {0}, {0}
861 0, {'h','t','t','p',':','/','/','w','w','w','.','t','e','s','t',0x15b,0x107,
862 '.','o','r','g','/','t','e','s','t','.','h','t','m','l',0},
863 "http://www.xn--test-ota71c.org/test.html", {'t','x','t',0}, {0}
866 0, {'w','w','w','.','T','e','s','t',0x15b,0x107,'.','o','r','g',
867 '/','t','e','s','t','.','h','t','m','l',0},
868 "www.Test\xc5\x9b\xc4\x87.org/test.html", {'a',0x106,'a',0}, {'b',0x106,'b',0}
871 0, {'H','t','t','p','s',':','/','/',0x15b,0x15b,0x107,'/','t',0x107,'/',
872 't','e','s','t','?','a','=','%','2','0',0x106,0},
873 "Https://xn--4da1oa/t\xc4\x87/test?a=%20\xc4\x86", {'a',0x15b,'a',0}, {'b',0x15b,'b',0}
876 12005, {'h','t','t','p','s',':','/','/','/','/',0x107,'.','o','r','g','/','t','e','s','t',0},
880 0, {'C','o','o','k','i','e',':',' ','u','s','e','r','@','t','e','s','t','.','o','r','g','/',0},
881 "Cookie: user@test.org/", {0}, {0}
884 static const FILETIME filetime_zero
;
886 WCHAR bufW
[MAX_PATH
];
891 win_skip("urlcache unicode functions\n");
895 for(i
=0; i
<ARRAY_SIZE(urls
); i
++) {
896 INTERNET_CACHE_ENTRY_INFOA
*entry_infoA
;
897 INTERNET_CACHE_ENTRY_INFOW
*entry_infoW
;
900 SetLastError(0xdeadbeef);
901 ret
= CreateUrlCacheEntryW(urls
[i
].url
, 0, NULL
, bufW
, 0);
902 if(urls
[i
].err
!= 0) {
903 ok(!ret
, "%ld) CreateUrlCacheEntryW succeeded\n", i
);
904 ok(urls
[i
].err
== GetLastError(), "%ld) GetLastError() = %ld\n", i
, GetLastError());
907 ok(ret
, "%ld) CreateUrlCacheEntryW failed: %ld\n", i
, GetLastError());
909 /* dwHeaderSize is ignored, pass 0 to prove it */
910 ret
= CommitUrlCacheEntryW(urls
[i
].url
, bufW
, filetime_zero
, filetime_zero
,
911 NORMAL_CACHE_ENTRY
, urls
[i
].header_info
, 0, urls
[i
].extension
, NULL
);
912 ok(ret
, "%ld) CommitUrlCacheEntryW failed: %ld\n", i
, GetLastError());
914 SetLastError(0xdeadbeef);
916 ret
= GetUrlCacheEntryInfoW(urls
[i
].url
, NULL
, &size
);
917 ok(!ret
&& GetLastError()==ERROR_INSUFFICIENT_BUFFER
,
918 "%ld) GetLastError() = %ld\n", i
, GetLastError());
919 entry_infoW
= HeapAlloc(GetProcessHeap(), 0, size
);
920 ret
= GetUrlCacheEntryInfoW(urls
[i
].url
, entry_infoW
, &size
);
921 ok(ret
, "%ld) GetUrlCacheEntryInfoW failed: %ld\n", i
, GetLastError());
923 ret
= GetUrlCacheEntryInfoA(urls
[i
].encoded_url
, NULL
, &size
);
924 ok(!ret
&& GetLastError()==ERROR_INSUFFICIENT_BUFFER
,
925 "%ld) GetLastError() = %ld\n", i
, GetLastError());
926 entry_infoA
= HeapAlloc(GetProcessHeap(), 0, size
);
927 ret
= GetUrlCacheEntryInfoA(urls
[i
].encoded_url
, entry_infoA
, &size
);
928 ok(ret
, "%ld) GetUrlCacheEntryInfoA failed: %ld\n", i
, GetLastError());
930 ok(entry_infoW
->dwStructSize
== entry_infoA
->dwStructSize
,
931 "%ld) entry_infoW->dwStructSize = %ld, expected %ld\n",
932 i
, entry_infoW
->dwStructSize
, entry_infoA
->dwStructSize
);
933 ok(!lstrcmpW(urls
[i
].url
, entry_infoW
->lpszSourceUrlName
),
934 "%ld) entry_infoW->lpszSourceUrlName = %s\n",
935 i
, wine_dbgstr_w(entry_infoW
->lpszSourceUrlName
));
936 ok(!lstrcmpA(urls
[i
].encoded_url
, entry_infoA
->lpszSourceUrlName
),
937 "%ld) entry_infoA->lpszSourceUrlName = %s\n",
938 i
, entry_infoA
->lpszSourceUrlName
);
939 ok(entry_infoW
->CacheEntryType
== entry_infoA
->CacheEntryType
,
940 "%ld) entry_infoW->CacheEntryType = %lx, expected %lx\n",
941 i
, entry_infoW
->CacheEntryType
, entry_infoA
->CacheEntryType
);
942 ok(entry_infoW
->dwUseCount
== entry_infoA
->dwUseCount
,
943 "%ld) entry_infoW->dwUseCount = %ld, expected %ld\n",
944 i
, entry_infoW
->dwUseCount
, entry_infoA
->dwUseCount
);
945 ok(entry_infoW
->dwHitRate
== entry_infoA
->dwHitRate
,
946 "%ld) entry_infoW->dwHitRate = %ld, expected %ld\n",
947 i
, entry_infoW
->dwHitRate
, entry_infoA
->dwHitRate
);
948 ok(entry_infoW
->dwSizeLow
== entry_infoA
->dwSizeLow
,
949 "%ld) entry_infoW->dwSizeLow = %ld, expected %ld\n",
950 i
, entry_infoW
->dwSizeLow
, entry_infoA
->dwSizeLow
);
951 ok(entry_infoW
->dwSizeHigh
== entry_infoA
->dwSizeHigh
,
952 "%ld) entry_infoW->dwSizeHigh = %ld, expected %ld\n",
953 i
, entry_infoW
->dwSizeHigh
, entry_infoA
->dwSizeHigh
);
954 ok(!memcmp(&entry_infoW
->LastModifiedTime
, &entry_infoA
->LastModifiedTime
, sizeof(FILETIME
)),
955 "%ld) entry_infoW->LastModifiedTime is incorrect\n", i
);
956 ok(!memcmp(&entry_infoW
->ExpireTime
, &entry_infoA
->ExpireTime
, sizeof(FILETIME
)),
957 "%ld) entry_infoW->ExpireTime is incorrect\n", i
);
958 ok(!memcmp(&entry_infoW
->LastAccessTime
, &entry_infoA
->LastAccessTime
, sizeof(FILETIME
)),
959 "%ld) entry_infoW->LastAccessTime is incorrect\n", i
);
960 ok(!memcmp(&entry_infoW
->LastSyncTime
, &entry_infoA
->LastSyncTime
, sizeof(FILETIME
)),
961 "%ld) entry_infoW->LastSyncTime is incorrect\n", i
);
963 MultiByteToWideChar(CP_ACP
, 0, entry_infoA
->lpszLocalFileName
, -1, bufW
, MAX_PATH
);
964 ok(!lstrcmpW(entry_infoW
->lpszLocalFileName
, bufW
),
965 "%ld) entry_infoW->lpszLocalFileName = %s, expected %s\n",
966 i
, wine_dbgstr_w(entry_infoW
->lpszLocalFileName
), wine_dbgstr_w(bufW
));
968 if(!urls
[i
].header_info
[0]) {
969 ok(!entry_infoW
->lpHeaderInfo
, "entry_infoW->lpHeaderInfo != NULL\n");
971 ok(!lstrcmpW((WCHAR
*)entry_infoW
->lpHeaderInfo
, urls
[i
].header_info
),
972 "%ld) entry_infoW->lpHeaderInfo = %s\n",
973 i
, wine_dbgstr_w((WCHAR
*)entry_infoW
->lpHeaderInfo
));
976 if(!urls
[i
].extension
[0]) {
977 ok(!entry_infoW
->lpszFileExtension
|| (ie10_cache
&& !entry_infoW
->lpszFileExtension
[0]),
978 "%ld) entry_infoW->lpszFileExtension = %s\n",
979 i
, wine_dbgstr_w(entry_infoW
->lpszFileExtension
));
981 MultiByteToWideChar(CP_ACP
, 0, entry_infoA
->lpszFileExtension
, -1, bufW
, MAX_PATH
);
982 ok(!lstrcmpW(entry_infoW
->lpszFileExtension
, bufW
) ||
983 (ie10_cache
&& !lstrcmpW(entry_infoW
->lpszFileExtension
, urls
[i
].extension
)),
984 "%ld) entry_infoW->lpszFileExtension = %s, expected %s\n",
985 i
, wine_dbgstr_w(entry_infoW
->lpszFileExtension
), wine_dbgstr_w(bufW
));
988 HeapFree(GetProcessHeap(), 0, entry_infoW
);
989 HeapFree(GetProcessHeap(), 0, entry_infoA
);
991 if(pDeleteUrlCacheEntryA
) {
992 ret
= pDeleteUrlCacheEntryA(urls
[i
].encoded_url
);
993 ok(ret
, "%ld) DeleteUrlCacheEntryW failed: %ld\n", i
, GetLastError());
998 static void test_FindCloseUrlCache(void)
1003 SetLastError(0xdeadbeef);
1004 r
= FindCloseUrlCache(NULL
);
1005 err
= GetLastError();
1006 ok(0 == r
, "expected 0, got %d\n", r
);
1007 ok(ERROR_INVALID_HANDLE
== err
, "expected %d, got %ld\n", ERROR_INVALID_HANDLE
, err
);
1010 static void test_GetDiskInfoA(void)
1013 DWORD error
, cluster_size
;
1014 DWORDLONG free
, total
;
1015 char path
[MAX_PATH
], *p
;
1017 GetSystemDirectoryA(path
, MAX_PATH
);
1018 if ((p
= strchr(path
, '\\'))) *++p
= 0;
1020 ret
= GetDiskInfoA(path
, &cluster_size
, &free
, &total
);
1021 ok(ret
, "GetDiskInfoA failed %lu\n", GetLastError());
1023 ret
= GetDiskInfoA(path
, &cluster_size
, &free
, NULL
);
1024 ok(ret
, "GetDiskInfoA failed %lu\n", GetLastError());
1026 ret
= GetDiskInfoA(path
, &cluster_size
, NULL
, NULL
);
1027 ok(ret
, "GetDiskInfoA failed %lu\n", GetLastError());
1029 ret
= GetDiskInfoA(path
, NULL
, NULL
, NULL
);
1030 ok(ret
, "GetDiskInfoA failed %lu\n", GetLastError());
1032 SetLastError(0xdeadbeef);
1033 strcpy(p
, "\\non\\existing\\path");
1034 ret
= GetDiskInfoA(path
, NULL
, NULL
, NULL
);
1035 error
= GetLastError();
1037 broken(old_ie
&& ret
), /* < IE7 */
1038 "GetDiskInfoA succeeded\n");
1039 ok(error
== ERROR_PATH_NOT_FOUND
||
1040 broken(old_ie
&& error
== 0xdeadbeef), /* < IE7 */
1041 "got %lu expected ERROR_PATH_NOT_FOUND\n", error
);
1043 SetLastError(0xdeadbeef);
1044 ret
= GetDiskInfoA(NULL
, NULL
, NULL
, NULL
);
1045 error
= GetLastError();
1046 ok(!ret
, "GetDiskInfoA succeeded\n");
1047 ok(error
== ERROR_INVALID_PARAMETER
, "got %lu expected ERROR_INVALID_PARAMETER\n", error
);
1050 static BOOL
cache_entry_exists(const char *url
)
1052 static char buf
[10000];
1053 DWORD size
= sizeof(buf
);
1056 ret
= GetUrlCacheEntryInfoA(url
, (void*)buf
, &size
);
1057 ok(ret
|| GetLastError() == ERROR_FILE_NOT_FOUND
, "GetUrlCacheEntryInfoA returned %x (%lu)\n", ret
, GetLastError());
1062 static void test_trailing_slash(void)
1064 char filename
[MAX_PATH
];
1068 static const FILETIME filetime_zero
;
1069 static char url_with_slash
[] = "http://testing.cache.com/";
1072 ret
= CreateUrlCacheEntryA(url_with_slash
, 0, "html", filename
, 0);
1073 ok(ret
, "CreateUrlCacheEntry failed with error %ld\n", GetLastError());
1075 create_and_write_file(filename
, &zero_byte
, sizeof(zero_byte
));
1077 ret
= CommitUrlCacheEntryA("Visited: http://testing.cache.com/", NULL
, filetime_zero
, filetime_zero
,
1078 NORMAL_CACHE_ENTRY
, NULL
, 0, "html", NULL
);
1079 ok(ret
, "CommitUrlCacheEntry failed with error %ld\n", GetLastError());
1081 ok(cache_entry_exists("Visited: http://testing.cache.com/"), "cache entry does not exist\n");
1082 ok(!cache_entry_exists("Visited: http://testing.cache.com"), "cache entry exists\n");
1084 ret
= DeleteUrlCacheEntryA("Visited: http://testing.cache.com/");
1085 ok(ret
, "DeleteCacheEntryA failed\n");
1086 DeleteFileA(filename
);
1089 static void get_cache_path(DWORD flags
, char path
[MAX_PATH
], char path_win8
[MAX_PATH
])
1093 const char *suffix
= "";
1094 const char *suffix_win8
= "";
1099 case CACHE_CONFIG_CONTENT_PATHS_FC
:
1100 folder
= CSIDL_INTERNET_CACHE
;
1101 suffix
= "\\Content.IE5\\";
1102 suffix_win8
= "\\IE\\";
1105 case CACHE_CONFIG_COOKIES_PATHS_FC
:
1106 folder
= CSIDL_COOKIES
;
1111 case CACHE_CONFIG_HISTORY_PATHS_FC
:
1112 folder
= CSIDL_HISTORY
;
1113 suffix
= "\\History.IE5\\";
1114 suffix_win8
= "\\History.IE5\\";
1118 ok(0, "unexpected flags %#lx\n", flags
);
1122 ret
= SHGetSpecialFolderPathA(0, path
, folder
, FALSE
);
1123 ok(ret
, "SHGetSpecialFolderPath error %lu\n", GetLastError());
1125 strcpy(path_win8
, path
);
1126 strcat(path_win8
, suffix_win8
);
1128 strcat(path
, suffix
);
1131 static void test_GetUrlCacheConfigInfo(void)
1133 INTERNET_CACHE_CONFIG_INFOA info
;
1136 INTERNET_CACHE_CONFIG_INFOA
*info
;
1143 #if 0 /* crashes under Vista */
1144 { NULL
, 0, 0, FALSE
, ERROR_INVALID_PARAMETER
},
1146 { &info
, 0, 0, TRUE
},
1147 { &info
, sizeof(info
) - 1, 0, TRUE
},
1148 { &info
, sizeof(info
) + 1, 0, TRUE
},
1149 { &info
, 0, CACHE_CONFIG_CONTENT_PATHS_FC
, TRUE
},
1150 { &info
, sizeof(info
), CACHE_CONFIG_CONTENT_PATHS_FC
, TRUE
},
1151 { &info
, 0, CACHE_CONFIG_COOKIES_PATHS_FC
, TRUE
},
1152 { &info
, sizeof(info
), CACHE_CONFIG_COOKIES_PATHS_FC
, TRUE
},
1153 { &info
, 0, CACHE_CONFIG_HISTORY_PATHS_FC
, TRUE
},
1154 { &info
, sizeof(info
), CACHE_CONFIG_HISTORY_PATHS_FC
, TRUE
},
1159 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
1163 memset(&info
, 0, sizeof(*td
[i
].info
));
1164 info
.dwStructSize
= td
[i
].dwStructSize
;
1167 SetLastError(0xdeadbeef);
1168 ret
= GetUrlCacheConfigInfoA(td
[i
].info
, NULL
, td
[i
].flags
);
1169 ok(ret
== td
[i
].ret
, "%d: expected %d, got %d\n", i
, td
[i
].ret
, ret
);
1171 ok(GetLastError() == td
[i
].error
, "%d: expected %lu, got %lu\n", i
, td
[i
].error
, GetLastError());
1174 char path
[MAX_PATH
], path_win8
[MAX_PATH
];
1176 get_cache_path(td
[i
].flags
, path
, path_win8
);
1178 ok(info
.dwStructSize
== td
[i
].dwStructSize
, "got %lu\n", info
.dwStructSize
);
1179 ok(!lstrcmpA(info
.CachePath
, path
) || !lstrcmpA(info
.CachePath
, path_win8
),
1180 "%d: expected %s or %s, got %s\n", i
, path
, path_win8
, info
.CachePath
);
1185 START_TEST(urlcache
)
1188 hdll
= GetModuleHandleA("wininet.dll");
1190 if(!GetProcAddress(hdll
, "InternetGetCookieExW")) {
1191 win_skip("Too old IE (older than 6.0)\n");
1194 if(!GetProcAddress(hdll
, "InternetGetSecurityInfoByURL")) /* < IE7 */
1197 if(GetProcAddress(hdll
, "CreateUrlCacheEntryExW")) {
1198 trace("Running tests on IE10 or newer\n");
1202 pDeleteUrlCacheEntryA
= (void*)GetProcAddress(hdll
, "DeleteUrlCacheEntryA");
1203 pUnlockUrlCacheEntryFileA
= (void*)GetProcAddress(hdll
, "UnlockUrlCacheEntryFileA");
1206 test_FindCloseUrlCache();
1207 test_GetDiskInfoA();
1208 test_trailing_slash();
1209 test_GetUrlCacheConfigInfo();